Re: Problem with ucontext_t struct in signal handler

Glynn Clements <[email protected]>
Newsgroups org.kernel.vger.linux-c-programming
Message-ID <[email protected]>
XComp wrote:

> I want to switch between user contexts using a signal handler  
> (something like a preemptive scheduler for userlevel threads). I've  
> found several sources, which say that it's not a good idea to use  
> setcontext or swapcontext in a signal handler. Nevertheless there also  
> exists at least one sample code of such an preemptive scheduler, which  
> seems to work well, at least on my machine (Ubuntu 8.04 with linux  
> kernel 2.6.24-22): www.seas.upenn.edu/~cse381/context_demo.c
> 
> // [...]
> static ucontext_t thread_context;
> static ucontext_t scheduler_context;
> 
> int thread_finished;
> int i;
> 
> static void simple_function(void) {
> 	// do nothing but counting
> 	for (i = 0; i < 1000000000; ++i) { }
> 
> 	if (i == 1000000000) {
> 		printf("\n[Thread Function]\t1st counting worked fine...");
> 	} else {
> 		printf("\n[Thread Function]\tError: Counting didn't finished  (%d)...", i);
> 	}
> 
> 	thread_finished = 1;
> }
> 
> static void other_function() {
> 	// thread_finished is a global variable, which is set to 1, if the  thread function is finished
> 	while(thread_finished != 1) { swapcontext(&scheduler_context,  &thread_context); }
> }
> 
> static void signal_handler_function(int sig_nr, siginfo_t* info, void  *old_context) {
> 	if (sig_nr == SIGPROF) {
> 		// saves the thread context
> 		thread_context = *((ucontext_t*) context);
> 
> 		// swaps back to scheduler context
> 		setcontext(&scheduler_context);
> 	}
> }
> // [...]
> 
> I ran into the following problem which belongs to the code above. I  
> interrupted simple_function several times by using a ITimer. But the  
> for-loop doesn't finish successfully everytime. Often the if condition  
> is false.

It seems likely that either the registers or the stack (wherever "i"
is stored) is getting trashed. What is "i" in the cases where the test
fails?

> But it does not cancel after the first signal is raised.  
> I've found out that using the third parameter old_context for storing  
> the old context is the reason. But I don't know why.

Note that the old_context parameter to the signal handler won't be
pointing to any of your context "slots". When a signal occurs, the
current context will be saved in a ucontext_t on the current context's
stack, and the old_context argument will point to that.

It needs to be borne in mind that a ucontext_t isn't "the context"
itself. It's merely a structure for storing information about a
context, either for receiving information (e.g. getcontext) or
providing it (e.g. setcontext).

> So I thought there might be a problem in the kernel. Am I right?

I don't think so.

> I was afraid to post the whole code, so I hope that this code
> snippet is enough.

It would help if it was accurate (e.g. the signal handler refers to
"context" which isn't declared anywhere; is this supposed to be the
old_context parameter?) and more complete.

> I would appreciate if someone can give me a comment whether this  
> strange behaviour is because of a wrong thinking of mine or because of  
> a error in the kernel which needs to be fixed.

I suspect the former.

-- 
Glynn Clements <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.