Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Jun 2004 00:45:28 -0700
From:      Sean McNeil <sean@mcneil.com>
To:        Daniel Eischen <eischen@vigrid.com>
Cc:        freebsd-threads@freebsd.org
Subject:   Re: signal handler priority issue
Message-ID:  <1086939928.10026.26.camel@server.mcneil.com>
In-Reply-To: <Pine.GSO.4.10.10406110242160.26412-100000@pcnet5.pcnet.com>
References:  <Pine.GSO.4.10.10406110242160.26412-100000@pcnet5.pcnet.com>

next in thread | previous in thread | raw e-mail | index | archive | help
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
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
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:

thread 1 calls pthread_kill for SIGUSR1.
thread 2 enters SIGUSR1 handler and SIGUSR2 is masked.
thread 1 calls pthread_kill for SIGUSR2. signal is set pending as it is
currently masked off.
thread 2 calls sigsuspend thus unblocking SIGUSR2.  Signal handler for
SIGUSR2 is called and then sigsuspend in SIGUSR1 handler returns.

Is this correct behavior?  Should a pthread_kill of a blocked signal
pend or should it be dropped?

Right now, I've worked around this.




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1086939928.10026.26.camel>