signal handler priority issue

Daniel Eischen eischen at vigrid.com
Fri Jun 11 08:10:40 GMT 2004


On Fri, 11 Jun 2004, Sean McNeil wrote:

> OK, I think I have it figured out....
> 
> The problem is, that when the first signal handler, SIGUSR1, is run the
> SIGUSR2 signal is blocked.  I think this is what Daniel was trying to
                   ^ not

> say, or I didn't provide enough information for him to catch it.  So,
> I've fixed the sigaction call to unblock SIGUSR2 while SIGUSR1 is going
                                   ^^^^^^^ block

> and rearranged a few things:
> 
>     me->stop_info.signal = 0;
>     me->stop_info.last_stop_count = my_stop_count;
> 
>     /* Tell the thread that wants to stop the world that this   */
>     /* thread has been stopped.  Note that sem_post() is  	*/
>     /* the only async-signal-safe primitive in LinuxThreads.    */
>     sem_post(&GC_suspend_ack_sem);
> 
> #if DEBUG_THREADS
>     GC_printf2("Waiting for restart #%d of 0x%lx\n", my_stop_count, my_thread);
> #endif
> 
>     /* Wait until that thread tells us to restart by sending    */
>     /* this thread a SIG_THR_RESTART signal.			*/
>     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
> 
>     while (me->stop_info.signal != SIG_THR_RESTART) {
> 	sigsuspend(&mask);             /* Wait for signal */
>     }
> 
> There might still be a bug that I'm just hiding.  I think that the
> problem is while in the handler for SIGUSR1 and someone calls
> pthread_kill with SIGUSR2, the signal isn't marked as pending because it
> is masked off.  It appears to rely on the following behavior:
     ^^^^^^^^^^

No, the problem is because SIGUSR2 is _not_ blocked.  I read
"masked off" as "blocked" (the desired behavior).  If the
signal handler runs, that means that the signal is not blocked.
Your goal is to prevent the signal handler (for SIGUSR2) from
running until sigsuspend() is hit.  Once sigsuspend() is hit,
then SIGUSR2 becomes unblocked, the signal handler is run,
and sigsuspend() returns.

> thread 1 calls pthread_kill for SIGUSR1.
> thread 2 enters SIGUSR1 handler and SIGUSR2 is masked.

Right!

> thread 1 calls pthread_kill for SIGUSR2. signal is set pending as it is
> currently masked off.

Right!

> thread 2 calls sigsuspend thus unblocking SIGUSR2.  Signal handler for
> SIGUSR2 is called and then sigsuspend in SIGUSR1 handler returns.

Exactly.

> Is this correct behavior?

It is correct behavior as long as your masks are set up correctly.

> Should a pthread_kill of a blocked signal
> pend or should it be dropped?

No, pthread_kill() does not pend; it is not like pthread_join().

> Right now, I've worked around this.

I'm not sure what you worked around.  The last few sentences are
the way you want it to work, not something to work around ;-)

-- 
Dan Eischen



More information about the freebsd-threads mailing list