Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 19 Jun 2002 17:40:09 -0400
From:      Daniel Eischen <eischen@vigrid.com>
To:        Andrew MacIntyre <andymac@bullseye.apana.org.au>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: signals in apps built with -pthread
Message-ID:  <3D10FA39.878E8703@vigrid.com>
References:  <Pine.OS2.4.32.0206192244550.74-200000@tenring.andymac.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Andrew MacIntyre wrote:
> 
> [originally posted to -questions on June 2, with no response.  If this
> doesn't belong on this list, please say so.]
> 
> This question is in the context of a scripting language interpreter
> (Python) which is built with threads (gcc -pthread), but which is
> used to run scripts which don't activate any threads.
> 
> In such instances, signal handling differs from an interpreter built
> without threads.
> 
> The attached C code is a simple example of a signal handling situation
> which works in the non-threaded interpreter, but fails in a threaded
> interpreter.
> 
> When compiled without -pthread (ie gcc -o sigp sigp.c), the attached code
> behaves as expected like so:
> 
> $ ./sigp
> 1,
> run 2
> $
> 
> When compiled with -pthread (ie gcc -pthread -o sigp sigp.c):
> 
> $ ./sigp
> 
> and then it hangs.  Sending it a SIGHUP from another terminal has no
> effect, but other likely signals (eg SIGINT) kill it.
> 
> There appears to have been a thread on a closely related topic, found at
> (long URL):
> http://groups.google.com/groups?hl=en&lr=&threadm=fa.n97llov.1lict2d%40ifi.uio.no
> 
> However, no information from that thread has illuminated the situation at
> hand.  Having two interpreter executables (with and without threads) is
> unpalatable.
> 
> Is there any way that the thread enabled interpreter can be setup to
> handle signals in the same way, in the absence of activated threads, as it
> would without thread support? (without disturbing the signal handling when
> threads _are_ activated, of course...)
> 
> Thanks for any advice,

Try the patch included at the bottom.

-- 
Dan Eischen

Index: uthread/uthread_sigpending.c
===================================================================
RCS file: /opt/FreeBSD/cvs/src/lib/libc_r/uthread/uthread_sigpending.c,v
retrieving revision 1.6
diff -u -r1.6 uthread_sigpending.c
--- uthread/uthread_sigpending.c	29 Jan 2000 22:53:53 -0000	1.6
+++ uthread/uthread_sigpending.c	19 Jun 2002 21:43:34 -0000
@@ -31,6 +31,9 @@
  *
  * $FreeBSD: src/lib/libc_r/uthread/uthread_sigpending.c,v 1.6 2000/01/29 22:53:53 jasone Exp $
  */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/signalvar.h>
 #include <signal.h>
 #include <errno.h>
 #ifdef _THREAD_SAFE
@@ -40,6 +43,7 @@
 int
 _sigpending(sigset_t * set)
 {
+	sigset_t sigset;
 	int ret = 0;
 
 	/* Check for a null signal set pointer: */
@@ -49,7 +53,10 @@
 	}
 	else {
 		*set = _thread_run->sigpend;
+		sigset = _process_sigpending;
+		SIGSETOR(*set, sigset);
 	}
+
 	/* Return the completion status: */
 	return (ret);
 }
Index: uthread/uthread_sigsuspend.c
===================================================================
RCS file: /opt/FreeBSD/cvs/src/lib/libc_r/uthread/uthread_sigsuspend.c,v
retrieving revision 1.9
diff -u -r1.9 uthread_sigsuspend.c
--- uthread/uthread_sigsuspend.c	27 Jan 2000 23:07:19 -0000	1.9
+++ uthread/uthread_sigsuspend.c	19 Jun 2002 21:35:57 -0000
@@ -31,6 +31,9 @@
  *
  * $FreeBSD: src/lib/libc_r/uthread/uthread_sigsuspend.c,v 1.9 2000/01/27 23:07:19 jasone Exp $
  */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/signalvar.h>
 #include <signal.h>
 #include <errno.h>
 #ifdef _THREAD_SAFE
@@ -41,7 +44,7 @@
 _sigsuspend(const sigset_t * set)
 {
 	int             ret = -1;
-	sigset_t        oset;
+	sigset_t        oset, sigset;
 
 	/* Check if a new signal set was provided by the caller: */
 	if (set != NULL) {
@@ -51,14 +54,30 @@
 		/* Change the caller's mask: */
 		_thread_run->sigmask = *set;
 
-		/* Wait for a signal: */
-		_thread_kern_sched_state(PS_SIGSUSPEND, __FILE__, __LINE__);
-
-		/* Always return an interrupted error: */
-		errno = EINTR;
+		/*
+		 * Check if there are pending signals for the running
+		 * thread or process that aren't blocked:
+		 */
+		sigset = _thread_run->sigpend;
+		SIGSETOR(sigset, _process_sigpending);
+		SIGSETNAND(sigset, _thread_run->sigmask);
+		if (SIGNOTEMPTY(sigset)) {
+			/*
+			 * Call the kernel scheduler which will safely
+			 * install a signal frame for the running thread:
+			 */
+			_thread_kern_sched_sig();
+		} else {
+			/* Wait for a signal: */
+			_thread_kern_sched_state(PS_SIGSUSPEND,
+			    __FILE__, __LINE__);
+		}
 
 		/* Restore the signal mask: */
 		_thread_run->sigmask = oset;
+
+		/* Always return an interrupted error: */
+		errno = EINTR;
 	} else {
 		/* Return an invalid argument error: */
 		errno = EINVAL;

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3D10FA39.878E8703>