makecontext segfault?
I am working开发者_如何学运维 on a homework assignment that will be due in the next semester. It requires us to implement our own context switching/thread library using the ucontext API. The professor provides code that does it, but before a thread returns, he manually does some work and calls an ISR that finds another thread to use and swap contexts to it or if none are left, exits.
The point of the assignment is to use the uc_link field of the context so that when it hits a return it takes care of the work. I've created a function (type void/void args) that just does the work the functions did before (clean up and then calls ISR). The professor said he wanted this.
So all that's left is to do a makecontext somewhere along the way on the context in the uc_link field so that it runs my thread, right? Well, when I do makecontext on seemingly any combination of ucontext_t's and function, I get a segfault and gdb provides no help. I can skip the makecontext and my program exits 'normally' when it hits a return in the threads I created because (presumably) the uc_link field is not properly setup (which is what I'm trying to do).
I also can't find anything on why makecontext would segfault. Can anyone help?
stack2.ss_sp = (void *)(malloc(STACKSIZE));
if(stack2.ss_sp == NULL){
printf("thread failed to get stack space\n");
exit(8);
}
stack2.ss_size = STACKSIZE;
stack2.ss_flags = 0;
if(getcontext(&main_context) == -1){
perror("getcontext in t_init, rtn_env");
exit(5);
}
//main_context.uc_stack = t_state[i].mystk;
main_context.uc_stack = stack2;
main_context.uc_link = 0;
makecontext(&main_context, (void (*)(void))thread_rtn, 0);
I've also tried just thread_rtn, &thread_rtn and other things. thread_rtn is declared as void thread_rtn(void).
Later, in each thread (run_env is of type ucontext_t): ...
t_state[i].run_env.uc_link = &main_context;
There is a lot going on here, but I'll give my best thoughts. I am also trying to answer the question without solving the homework.
In what context is thread_rtn
declared, and does it use any non-static variables?
The segfault is likely cause by memory that was allocated but is no longer available (out of context or freed).
I can't tell if the main_context
is the same as the thread context, the two should be different.
It looks like each thread needs its own stack, which should not be the same as the stack of the main context (or the sam as any other thread's stack). Think about where each thread could get memory to use as a stack. Under what conditions would malloc(STACKSIZE)
return NULL
?
When a thread context is added to the main context, main_context.uc_link
should be incremented. It looks like main_context.uc_link
is keeping track of how many threads are linked to the main context. Think about what happens when the count decreases (I'm trying to leave some thoughwork relevant to the course rather than saying what to do about a decreasing count). Note the special value of 0, meaning that there are no longer any threads associated with this main context. Is there a maximum value for main_context.uc_link
?
Hope this helps.
I had exactly same problem and after quite a lot of debugging, I found the solution.
The makecontext() requires you to pass the bottom of the stack and it calculates the top of stack automatically from the size passed to it.
In my case,
Because in linux,the stack grows from top to bottom,I was passing the top of the stack as required by clone system call. So, it was giving segmentation fault.
Just try it out and maybe it works.
I encountered the same error, I figure it out, the reason of the error is the size of stack was too small, increase it, and the error was gone.
pco->_context.uc_stack.ss_sp = _stack.get();
// change STACKSIZE from 2<<10 to 2<<20, the error was fixed!
pco->_context.uc_stack.ss_size = STACKSIZE;
精彩评论