bin/49087: Signals lost in programs linked with libc_r
Anton Berezin
tobez at FreeBSD.org
Wed Apr 16 07:00:35 PDT 2003
The following reply was made to PR bin/49087; it has been noted by GNATS.
From: Anton Berezin <tobez at FreeBSD.org>
To: Enache Adrian <enache at rdslink.ro>
Cc: FreeBSD-gnats-submit at FreeBSD.org, fjoe at FreeBSD.org,
deischen at FreeBSD.org, marcel at FreeBSD.org
Subject: Re: bin/49087: Signals lost in programs linked with libc_r
Date: Wed, 16 Apr 2003 15:56:42 +0200
On Mon, Mar 10, 2003 at 11:28:34PM +0200, Enache Adrian wrote:
> FreeBSD seems to lose blocked signals in programs linked
> with libc_r. This bug shows up when running the perl
> test suite with a multithreaded perl ( i.e. linked to
> libc_r.so ), more precisely at test 11 of ext/POSIX/t/posix.t.
> -----< sig.c >---------------------------------------------------
> #include <unistd.h>
> #include <signal.h>
> #include <stdio.h>
>
> void sighup(int dummy)
> {
> kill(getpid(),SIGINT);
> sleep(1);
> printf("sigint delayed ...\n");
> }
>
> void sigint(int dummy)
> {
> printf("SIGINT !\n");
> }
>
> struct sigaction act;
>
> int main()
> {
> act.sa_handler = sighup;
> sigaddset(&act.sa_mask, SIGINT);
> sigaction(SIGHUP, &act, NULL);
> signal(SIGINT,sigint);
> kill(getpid(),SIGHUP);
> sleep(2);
> printf("*\n");
> return 0;
> }
> -----------------------------------------------------------------
> Any pointers appreciated.
Please try the following patch (tested an identical patch on 4.8; not
tested with -current):
Index: uthread_sig.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_sig.c,v
retrieving revision 1.45
diff -u -r1.45 uthread_sig.c
--- uthread_sig.c 5 Mar 2003 04:28:08 -0000 1.45
+++ uthread_sig.c 16 Apr 2003 13:45:36 -0000
@@ -257,6 +257,7 @@
void (*sigfunc)(int, siginfo_t *, void *);
int saved_seqno;
sigset_t saved_sigmask;
+ sigset_t sigset;
/* Invoke the signal handler without going through the scheduler:
*/
@@ -288,8 +289,26 @@
* Only restore the signal mask if it hasn't been changed by the
* application during invocation of the signal handler:
*/
- if (curthread->sigmask_seqno == saved_seqno)
+ if (curthread->sigmask_seqno == saved_seqno) {
curthread->sigmask = saved_sigmask;
+
+ /*
+ * Just like in _pthread_sigmask(), check if
+ * there are pending signals for the running
+ * thread or process that aren't blocked.
+ * This avoids losing signals when sigaction() with
+ * non-empty sa_mask is used.
+ */
+ sigset = curthread->sigpend;
+ SIGSETOR(sigset, _process_sigpending);
+ SIGSETNAND(sigset, curthread->sigmask);
+ if (SIGNOTEMPTY(sigset))
+ /*
+ * Call the kernel scheduler which will safely
+ * install a signal frame for the running thread:
+ */
+ _thread_kern_sched_sig();
+ }
}
/*
I would be *glad* if a person which knows uthreads better than I do
reviews the patch and tells me that I am wrong and where I am wrong.
:-) That's why I am Ccing three random uthread_sig.c committers.
Cheers,
%Anton.
--
Perl is strongly typed, it just has very few types. -- Dan Sugalski
More information about the freebsd-bugs
mailing list