signal handler priority issue

Sean McNeil sean at mcneil.com
Fri Jun 11 04:41:39 GMT 2004


On Thu, 2004-06-10 at 21:19, Daniel Eischen wrote:
> On Thu, 10 Jun 2004, Sean McNeil wrote:
> 
> > I'm working on kse support for gcc/gcj/gij and ran into an interesting
> > problem with signals:
> > 
> > Each thread installs a signal handler for synchronization.  This signal
> > handler does a sem_post() to inform it has suspended then goes into a
> > sigsuspend() loop waiting for a signal that has no handler attached to
> > it.  So we have
> 
> You might want to look and see how GNAT handles synchronization
> between tasks; it should be merged into the gcc baseline.

This is for boehm-gc and it works for libc_r but not for kse.

> > SIGUSR1 - signal handler attached to suspend the thread
> > SIGUSR2 - no signal handler but waited on in sigsuspend() within the
> > above handler.
> 
> Each thread has a signal handler for SIGUSR1?

Yes, the statement below was a typo.  The thread is sent the signal via
pthread_kill as SIGUSR1 to suspend and SIGUSR2 to resume.

> > When you want to have exclusive access, you loop through and stop each
>                                                                ^^^^ suspend?
> 
> > thread by sending the SIGUSR2 and wait on the semaphore it posts to. 
>                         ^^^^^^^ SIGUSR1?

This it the typo. should be SIGUSR1.

> > Then you do your thing.  When done, you signal each thread with SIGUSR2.
> 
> > The problem I'm seeing is that the signal handler doesn't have
> > pririority thus it goes to sleep on the sem_post and the SIGUSR2 signal
> > is lost because it happens before the sigsuspend() is invoked.
> 
> It doesn't matter.  If a signal is sent to a thread (via pthread_kill())
> and that signal is masked, then the signal is added to the thread's
> pending signals.  If it hits sigsuspend() at a later point in time
> and any pending signals are unmasked, then it returns after processing
> those pending signals.
> 
> Also, don't confuse kill() with pthread_kill().  If you try to
> use kill(), it can go to any thread in the process whose signal
> is unmasked.
> 
> > I think there is something missing or not functioning in sem_post that
> > should prevent the signal handler from losing the cpu.  I see there is
> > an enter/exit critical in there.  Should that prevent it from context
> > switching?  It would appear not in that exiting a critical section will
> > cause a yield.
> 
> A "thread" critical section prevents the thread from getting
> signals or otherwise interrupted.  If the thread blocks on
> a low-level lock, then it will get swapped out for another
> thread.
> 
> > Any help on figuring out how to fix this would be appreciated.  Perhaps
> > someone more familiar with kse can tell me how to go about changing it
> > so that a signal handler cannot cause a yield.  Perhaps something in
> > _thr_sig_handler?
> 
> The critical section should prevent the signal handler
> from being invoked.  Put some printf()'s in after the
> sem_post() and in the signal handler().  The signal
> handler printf()'s should always occur after the sem_post().
> Plus, you shouldn't be getting that signal since it
> should be masked until sigsuspend() is called.
> 
> Is it getting past sem_post() and into sigsuspend() or not?
> If it is getting past sem_post(), then I don't think that is
> your problem.

Here is what I see:

master thread calls pthread_kill with SIGUSR1 and waits on semaphore.
other thread gets signal and calls sem_post.  It yields the scheduler.
master thread gets semaphore and continues on it's way.
master thread calls pthread_kill with SIGUSR2 and keeps going.
Later, master calls pthread_kill with SIGUSR1 and waits on semaphore.
other thread gets signal and calls sem_post.  It yields the scheduler.
master thread gets semaphore and continues on it's way.
master thread calls pthread_kill with SIGUSR2 and keeps going.
Finally, master scheduler is done and yields the scheduler.
other thread gets to run now and then it goes into sigsuspend waiting
for SIGUSR2, but it never gets it because it wasn't masked until
sigsuspend is called.
threads are all hung.

The problem is that sem_post should not cause a reschedule of threads
when inside a signal handler and it does.

Cheers,
Sean




More information about the freebsd-threads mailing list