signal handler priority issue

Daniel Eischen eischen at vigrid.com
Fri Jun 11 06:42:13 GMT 2004


On Thu, 10 Jun 2004, Sean McNeil wrote:

> On Thu, 2004-06-10 at 23:06, Daniel Eischen wrote:
> > 
> > Like I said before, it depends on the mask of the installed
> > signal handler (sigact.sa_mask).  You should use sigaction()
> > and not signal() to get the desired behavior.
> > 
> > You're other output looked strange.  I was expecting the
> > "restart" count to start at 1, not 2.
> 
> That is my fault.  I didn't give enough output.  That count is how many
> times world is stopped.  Here is all the output:
> 
> Stopping the world from 0x50d000
> World stopped from 0x50d000
> Pushing stacks from thread 0x50d000
> Stack for thread 0x50d000 = [7fffffffdfa0,800000000000)
> World starting
> World started
> About to start new thread from thread 0x50D000
> Started thread 0x9D1400
> Starting thread 0x9d1400
> pid = 85636
> sp = 0x7fffffeedf80
> start_routine = 0x200db4960
> Unable to locate tools.jar. Expected to find it in /usr/local/gcc-cvs/lib/tools.jar
> Stopping the world from 0x50d000
> Sending suspend signal to 0x9d1400
> Suspending 0x9d1400
> World stopped from 0x50d000
> Pushing stacks from thread 0x50d000
> Stack for thread 0x9d1400 = [7fffffeed94c,7fffffeee000)
> Stack for thread 0x50d000 = [7fffffffcf00,800000000000)
> World starting
> Sending restart signal to 0x9d1400
> World started
> In GC_restart_handler for 0x9d1400
> Waiting for restart #2 of 0x9d1400
> Buildfile: build.xml
> Stopping the world from 0x50d000
> Sending suspend signal to 0x9d1400
> 
> This is with the following change to the code, by the way, that masks
> everything but the (SIG_THR_RESTART) SIGUSR2 before calling sem_post. So
> that didn't solve my problem:
> 
>     /* Wait until that thread tells us to restart by sending    */
>     /* this thread a SIG_THR_RESTART signal.			*/
>     /* SIG_THR_RESTART should be masked at this point.  Thus there	*/
>     /* is no race.						*/
>     if (sigfillset(&mask) != 0) ABORT("sigfillset() failed");
>     if (sigdelset(&mask, SIG_THR_RESTART) != 0) ABORT("sigdelset()
> failed");
> #   ifdef NO_SIGNALS
>       if (sigdelset(&mask, SIGINT) != 0) ABORT("sigdelset() failed");
>       if (sigdelset(&mask, SIGQUIT) != 0) ABORT("sigdelset() failed");
>       if (sigdelset(&mask, SIGTERM) != 0) ABORT("sigdelset() failed");
>       if (sigdelset(&mask, SIGABRT) != 0) ABORT("sigdelset() failed");
> #   endif
> 
>     pthread_sigmask(SIG_SETMASK, &mask, NULL);

This isn't correct.  You're unmasking SIG_THR_RESTART, not masking
it.  See the sigfillset() above followed by sigdelset().
Also, by masking it here in the signal handler instead of
where the signal handler is installed, you have to unmask
it after sigsuspend() returns.  And actually, you have to
return the signal mask to the state from before the signal handler
was invoked.

The best and easiest way is to just mask SIG_THR_RESTART
in act.sa_mask from wherever the handler is installed.
The other way is to install the signal handler with SA_SIGINFO
and grab the original mask from ucp->uc_sigmask (which will
be the 3rd argument to the signal handler) and use that to
restore it.

See David's email for how to mask SIG_THR_RESTART when the
signal handler is installed.

-- 
Dan Eischen



More information about the freebsd-threads mailing list