Reputation: 129
I was working on a project for a course on Operating Systems. The task was to implement a library for dealing with threads, similar to pthreads
, but much more simpler. The purpose of it is to practice scheduling algorithms. The final product is a .a
file. The course is over and everything worked just fine (in terms of functionality).
Though, I got curious about an issue I faced. On three different functions of my source file, if I add the following line, for instance:
fprintf(stderr, "My lucky number is %d\n", 4);
I get a segmentation fault. The same doesn't happen if stdout
is used instead, or if the formatting doesn't contain any variables.
That leaves me with two main questions:
Why does it only happen in three functions of my code, and not the others?
Could the creation of contexts using getcontext()
and makecontext()
, or the changing of contexts using setcontext()
or swapcontext()
mess up with the standard file descriptors?
My intuition says those functions could be responsible for that. Even more when given the fact that the three functions of my code in which this happens are functions that have contexts which other parts of the code switch to. Usually by setcontext()
, though swapcontext()
is used to go to the scheduler, for choosing another thread to execute.
Additionally, if that is the case, then:
I'm currently doing the following:
/*------------------------------------------------------------------------------
Funct: Creates an execution context for the function and arguments passed.
Input: uc -> Pointer where the context will be created.
funct -> Function to be executed in the context.
arg -> Argument to the function.
Return: If the function succeeds, 0 will be returned. Otherwise -1.
------------------------------------------------------------------------------*/
static int create_context(ucontext_t *uc, void *funct, void *arg)
{
if(getcontext(uc) != 0) // Gets a context "model"
{
return -1;
}
stack_t *sp = (stack_t*)malloc(STACK_SIZE); // Stack area for the execution context
if(!sp) // A stack area is mandatory
{
return -1;
}
uc->uc_stack.ss_sp = sp; // Sets stack pointer
uc->uc_stack.ss_size = STACK_SIZE; // Sets stack size
uc->uc_link = &context_end; // Sets the context to go after execution
makecontext(uc, funct, 1, arg); // "Makes everything work" (can't fail)
return 0;
}
This code is probably a little modified, but it is originally an online example on how to use u_context.
Upvotes: 1
Views: 1089
Reputation: 33717
Assuming glibc, the explanation is that fprintf
with an unbuffered stream (such as stderr
by default) internally creates an on-stack buffer which as a size of BUFSIZE
bytes. See the function buffered_vfprintf
in stdio-common/vfprintf.c
. BUFSIZ
is 8192, so you end up with a stack overflow because the stack you create is too small.
Upvotes: 4