Date: Tue, 19 Dec 2000 18:56:14 +0100 (CET) From: tobez@tobez.org To: FreeBSD-gnats-submit@freebsd.org Cc: deischen@freebsd.org, jasone@freebsd.org Subject: bin/23647: libc_r: non-delivery of previously blocked signals Message-ID: <200012191756.eBJHuEv89695@aylee.t-d.rh.dk> Resent-Message-ID: <200012191800.eBJI0BE38857@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 23647
>Category: bin
>Synopsis: libc_r: non-delivery of previously blocked signals
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Tue Dec 19 10:00:04 PST 2000
>Closed-Date:
>Last-Modified:
>Originator: Anton Berezin
>Release: FreeBSD 5.0-CURRENT i386
>Organization:
self
>Environment:
Relatively recent 5.0-CURRENT and 4.2-STABLE.
>Description:
In the program below the SIGINT signal should be delivered immediately
after SIGHUP handler returns. This does not happen on recent -current
and -stable boxes.
The same program compiled with libc works fine. It also works right on
3.5, 4.1.1 and older -current boxes.
It appears that pending signals are simply discarded in
_thread_sig_handle_pending() after thread_sig_find() being unable to
find the thread to deliver the signal due to the signal being blocked.
>How-To-Repeat:
Run the following program compiled with -pthread. The expected output
is `:-)', any other output is wrong.
#include <sys/types.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
char sequence[64];
int seqi = 0;
int self;
void hupper(int s)
{
sequence[seqi++] = ':';
kill(self,SIGINT);
sleep(2);
sequence[seqi++] = '-';
}
void inter(int s)
{
sequence[seqi++] = ')';
}
int main(void)
{
struct sigaction sa;
self = getpid();
bzero(&sa, sizeof(sa));
sa.sa_handler = hupper;
sigaddset(&sa.sa_mask, SIGINT);
sigaction(SIGHUP, &sa, NULL);
signal(SIGINT, inter);
kill(self,SIGHUP);
sleep(1);
sequence[seqi++] = '\0';
printf("%s\n", sequence);
return 0;
}
>Fix:
I am too unfamiliar with uthread code, so I am afraid the fix below a)
slows down _thread_kern_scheduler(); and b) might break some things.
Nevertheless, here is my take:
--- lib/libc_r/uthread/uthread_kern.c.orig Tue Dec 19 18:19:19 2000
+++ lib/libc_r/uthread/uthread_kern.c Tue Dec 19 18:28:37 2000
@@ -203,6 +203,11 @@ _thread_kern_scheduler(void)
_thread_sig_check_pending(_thread_run);
}
+ /* Handle any pending signals */
+ _queue_signals = 1;
+ dequeue_signals();
+ _queue_signals = 0;
+
/*
* Enter a scheduling loop that finds the next thread that is
* ready to run. This loop completes when there are no more threads
--- lib/libc_r/uthread/uthread_sig.orig Tue Dec 19 18:19:31 2000
+++ lib/libc_r/uthread/uthread_sig.c Tue Dec 19 18:26:21 2000
@@ -483,6 +483,14 @@ _thread_sig_handle_pending(void)
*/
thread_sig_add(pthread, sig,
/*has_args*/ 1);
+ } else {
+ /*
+ * We do not want to accidentally
+ * loose the signal, will try to
+ * handle it at some later time:
+ */
+ _thread_sigq[i].blocked = 0;
+ _thread_sigq[i].pending = 1;
}
}
}
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200012191756.eBJHuEv89695>
