summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMarco S Hyman <marc@cvs.openbsd.org>2002-10-30 19:11:57 +0000
committerMarco S Hyman <marc@cvs.openbsd.org>2002-10-30 19:11:57 +0000
commit5b3d505b4e254da05bc3ffa547a6e9f65798bf3d (patch)
tree0ceb12589bb4b87bde661f6909649e57f1b16c15 /lib
parent2051a2b3c5d4ccdbc313073e0e948ca64da5d8e7 (diff)
signal handling changes. This corrects several signal
handling errors in the threads library. Most of the libc_r regression tests are now ok. thread specific kill semantics are still not correct. No negative comments after posting to tech@ a week or so ago. siginfo test fails on sparc64 due to sparc64 oddity.
Diffstat (limited to 'lib')
-rw-r--r--lib/libc_r/uthread/pthread_private.h10
-rw-r--r--lib/libc_r/uthread/uthread_accept.c39
-rw-r--r--lib/libc_r/uthread/uthread_exit.c4
-rw-r--r--lib/libc_r/uthread/uthread_init.c7
-rw-r--r--lib/libc_r/uthread/uthread_kern.c75
-rw-r--r--lib/libc_r/uthread/uthread_kill.c13
-rw-r--r--lib/libc_r/uthread/uthread_mutex.c23
-rw-r--r--lib/libc_r/uthread/uthread_sig.c300
-rw-r--r--lib/libc_r/uthread/uthread_sigaction.c17
-rw-r--r--lib/libc_r/uthread/uthread_signal.c4
-rw-r--r--lib/libc_r/uthread/uthread_sigwait.c4
-rw-r--r--lib/libpthread/uthread/pthread_private.h10
-rw-r--r--lib/libpthread/uthread/uthread_accept.c39
-rw-r--r--lib/libpthread/uthread/uthread_exit.c4
-rw-r--r--lib/libpthread/uthread/uthread_init.c7
-rw-r--r--lib/libpthread/uthread/uthread_kern.c75
-rw-r--r--lib/libpthread/uthread/uthread_kill.c13
-rw-r--r--lib/libpthread/uthread/uthread_mutex.c23
-rw-r--r--lib/libpthread/uthread/uthread_sig.c300
-rw-r--r--lib/libpthread/uthread/uthread_sigaction.c17
-rw-r--r--lib/libpthread/uthread/uthread_signal.c4
-rw-r--r--lib/libpthread/uthread/uthread_sigwait.c4
22 files changed, 506 insertions, 486 deletions
diff --git a/lib/libc_r/uthread/pthread_private.h b/lib/libc_r/uthread/pthread_private.h
index 23723ca68e0..88341872451 100644
--- a/lib/libc_r/uthread/pthread_private.h
+++ b/lib/libc_r/uthread/pthread_private.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pthread_private.h,v 1.35 2002/02/21 20:57:41 fgsch Exp $ */
+/* $OpenBSD: pthread_private.h,v 1.36 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -1082,8 +1082,9 @@ __BEGIN_DECLS
int _find_thread(pthread_t);
struct pthread *_get_curthread(void);
void _set_curthread(struct pthread *);
-int _thread_create(pthread_t *,const pthread_attr_t *,void *(*start_routine)(void *),void *,pthread_t);
-void _dispatch_signals(void);
+int _thread_create(pthread_t *, const pthread_attr_t *,
+ void *(*start_routine)(void *), void *,pthread_t);
+void _dispatch_signals(pthread_t, struct sigcontext *);
void _thread_signal(pthread_t, int);
int _mutex_cv_lock(pthread_mutex_t *);
int _mutex_cv_unlock(pthread_mutex_t *);
@@ -1115,9 +1116,10 @@ void _thread_kern_sched_state_unlock(enum pthread_state state,
void _thread_kern_set_timeout(const struct timespec *);
void _thread_kern_sig_defer(void);
void _thread_kern_sig_undefer(void);
-void _thread_sig_handler(int, int, struct sigcontext *);
+void _thread_sig_handler(int, siginfo_t *, struct sigcontext *);
void _thread_sig_handle(int, struct sigcontext *);
void _thread_sig_init(void);
+void _thread_sig_process(int, struct sigcontext *);
void _thread_start(void);
void _thread_start_sig_handler(void);
void _thread_seterrno(pthread_t,int);
diff --git a/lib/libc_r/uthread/uthread_accept.c b/lib/libc_r/uthread/uthread_accept.c
index 23197f8dadc..9c4b1d81eca 100644
--- a/lib/libc_r/uthread/uthread_accept.c
+++ b/lib/libc_r/uthread/uthread_accept.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_accept.c,v 1.5 2001/08/21 19:24:53 fgsch Exp $ */
+/* $OpenBSD: uthread_accept.c,v 1.6 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -52,7 +52,8 @@ accept(int fd, struct sockaddr * name, socklen_t *namelen)
/* Enter a loop to wait for a connection request: */
while ((ret = _thread_sys_accept(fd, name, namelen)) < 0) {
/* Check if the socket is to block: */
- if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
/* Save the socket file descriptor: */
curthread->data.fd.fd = fd;
curthread->data.fd.fname = __FILE__;
@@ -63,7 +64,8 @@ accept(int fd, struct sockaddr * name, socklen_t *namelen)
curthread->interrupted = 0;
/* Schedule the next thread: */
- _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__);
+ _thread_kern_sched_state(PS_FDR_WAIT, __FILE__,
+ __LINE__);
/* Check if the wait was interrupted: */
if (curthread->interrupted) {
@@ -81,26 +83,19 @@ accept(int fd, struct sockaddr * name, socklen_t *namelen)
}
}
- /* Check for errors: */
- if (ret < 0) {
- }
- /* Initialise the file descriptor table for the new socket: */
- else if (_thread_fd_table_init(ret) != 0) {
- /* Quietly close the socket: */
- _thread_sys_close(ret);
-
- /* Return an error: */
- ret = -1;
- }
- /*
- * If the parent socket was blocking, make sure that
- * the new socket is also set blocking here (as the
- * call to _thread_fd_table_init() above will always
- * set the new socket flags to non-blocking, as that
- * will be the inherited state of the new socket.
+ /*
+ * If no errors initialize the file descriptor table
+ * for the new socket. Turn on blocking mode in the
+ * child if it is on in the parent. This is done
+ * as _thread_fd_table_init *may* have turned the flag on.
*/
- if((ret > 0) && (_thread_fd_table[fd]->flags & O_NONBLOCK) == 0)
- _thread_fd_table[ret]->flags &= ~O_NONBLOCK;
+ if (ret != -1)
+ if (_thread_fd_table_init(ret) != 0) {
+ /* Quietly close the socket: */
+ _thread_sys_close(ret);
+ ret = -1;
+ } else if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0)
+ _thread_fd_table[ret]->flags &= ~O_NONBLOCK;
/* Unlock the file descriptor: */
_FD_UNLOCK(fd, FD_RDWR);
diff --git a/lib/libc_r/uthread/uthread_exit.c b/lib/libc_r/uthread/uthread_exit.c
index a7a0c60a267..27ed0903ea6 100644
--- a/lib/libc_r/uthread/uthread_exit.c
+++ b/lib/libc_r/uthread/uthread_exit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_exit.c,v 1.15 2001/12/19 02:02:52 fgsch Exp $ */
+/* $OpenBSD: uthread_exit.c,v 1.16 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -132,7 +132,7 @@ _thread_exit(const char *fname, int lineno, const char *string)
/* Set the abort handler to default (dump core) */
sa.sa_handler = SIG_DFL;
sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
+ sa.sa_flags = SA_SIGINFO;
(void)_thread_sys_sigaction(SIGABRT, &sa, NULL);
(void)_thread_sys_kill(_thread_sys_getpid(), SIGABRT);
for (;;) ;
diff --git a/lib/libc_r/uthread/uthread_init.c b/lib/libc_r/uthread/uthread_init.c
index d9f398c381b..803e46e1fe8 100644
--- a/lib/libc_r/uthread/uthread_init.c
+++ b/lib/libc_r/uthread/uthread_init.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_init.c,v 1.21 2002/02/21 20:57:41 fgsch Exp $ */
+/* $OpenBSD: uthread_init.c,v 1.22 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -222,7 +222,7 @@ _thread_init(void)
/* Initialise the global signal action structure: */
sigfillset(&act.sa_mask);
act.sa_handler = (void (*) ()) _thread_sig_handler;
- act.sa_flags = 0;
+ act.sa_flags = SA_SIGINFO;
/* Clear pending signals for the process: */
sigemptyset(&_process_sigpending);
@@ -263,6 +263,9 @@ _thread_init(void)
*/
PANIC("Cannot initialize signal handler");
}
+ _thread_sigact[_SCHED_SIGNAL - 1].sa_flags = SA_SIGINFO;
+ _thread_sigact[SIGINFO - 1].sa_flags = SA_SIGINFO;
+ _thread_sigact[SIGCHLD - 1].sa_flags = SA_SIGINFO;
/* Get the process signal mask: */
_thread_sys_sigprocmask(SIG_SETMASK, NULL, &_process_sigmask);
diff --git a/lib/libc_r/uthread/uthread_kern.c b/lib/libc_r/uthread/uthread_kern.c
index da3c91ff933..f7db1f0871b 100644
--- a/lib/libc_r/uthread/uthread_kern.c
+++ b/lib/libc_r/uthread/uthread_kern.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_kern.c,v 1.21 2002/02/21 20:57:41 fgsch Exp $ */
+/* $OpenBSD: uthread_kern.c,v 1.22 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -50,15 +50,19 @@
#include <pthread.h>
#include "pthread_private.h"
-/* Static function prototype definitions: */
-static void
-thread_kern_poll(int wait_reqd);
-
-static void
-dequeue_signals(void);
+#if defined(PTHREAD_TRACE_KERN)
+#define PTHREAD_TRACE(x) _thread_sys_write(-1, (void*) x, 0)
+#else
+#define PTHREAD_TRACE(x)
+#endif
-static inline void
-thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in);
+/*
+ * local functions. Do NOT make these static... we want so see them in
+ * crash dumps.
+ */
+void _thread_kern_poll(int);
+void _dequeue_signals(void);
+inline void _thread_run_switch_hook(pthread_t, pthread_t);
/* Static variables: */
static int last_tick = 0;
@@ -68,6 +72,7 @@ _thread_kern_sched_sig(void)
{
struct pthread *curthread = _get_curthread();
+ PTHREAD_TRACE(1);
curthread->check_pending = 1;
_thread_kern_sched(NULL);
}
@@ -83,6 +88,8 @@ _thread_kern_sched(struct sigcontext * scp)
int add_to_prioq;
pthread_t old_thread_run;
+ PTHREAD_TRACE(2);
+
/*
* Flag the pthread kernel as executing scheduler code
* to avoid a scheduler signal from interrupting this
@@ -291,7 +298,7 @@ _thread_kern_sched(struct sigcontext * scp)
* Poll file descriptors to update the state of threads
* waiting on file I/O where data may be available:
*/
- thread_kern_poll(0);
+ _thread_kern_poll(0);
/* Protect the scheduling queues: */
_queue_signals = 1;
@@ -409,7 +416,7 @@ _thread_kern_sched(struct sigcontext * scp)
* There are no threads ready to run, so wait until
* something happens that changes this condition:
*/
- thread_kern_poll(1);
+ _thread_kern_poll(1);
/*
* This process' usage will likely be very small
@@ -445,7 +452,7 @@ _thread_kern_sched(struct sigcontext * scp)
/* Protect the scheduling queues again: */
_queue_signals = 1;
- dequeue_signals();
+ _dequeue_signals();
/*
* Check for a higher priority thread that
@@ -519,7 +526,7 @@ _thread_kern_sched(struct sigcontext * scp)
*/
if ((_sched_switch_hook != NULL) &&
(_last_user_thread != curthread)) {
- thread_run_switch_hook(_last_user_thread,
+ _thread_run_switch_hook(_last_user_thread,
curthread);
}
@@ -543,7 +550,7 @@ _thread_kern_sched(struct sigcontext * scp)
if (_sched_switch_hook != NULL) {
/* Run the installed switch hook: */
- thread_run_switch_hook(_last_user_thread,
+ _thread_run_switch_hook(_last_user_thread,
curthread);
}
@@ -569,6 +576,7 @@ _thread_kern_sched_state(enum pthread_state state, char *fname, int lineno)
{
struct pthread *curthread = _get_curthread();
+ PTHREAD_TRACE(3);
/*
* Flag the pthread kernel as executing scheduler code
* to avoid a scheduler signal from interrupting this
@@ -597,6 +605,8 @@ _thread_kern_sched_state_unlock(enum pthread_state state,
{
struct pthread *curthread = _get_curthread();
+ PTHREAD_TRACE(4);
+
/*
* Flag the pthread kernel as executing scheduler code
* to avoid a scheduler signal from interrupting this
@@ -622,8 +632,8 @@ _thread_kern_sched_state_unlock(enum pthread_state state,
_thread_kern_sched(NULL);
}
-static void
-thread_kern_poll(int wait_reqd)
+void
+_thread_kern_poll(int wait_reqd)
{
int count = 0;
int i, found;
@@ -634,6 +644,8 @@ thread_kern_poll(int wait_reqd)
struct timespec ts;
struct timeval tv;
+ PTHREAD_TRACE(5);
+
/* Check if the caller wants to wait: */
if (wait_reqd == 0) {
timeout_ms = 0;
@@ -683,8 +695,7 @@ thread_kern_poll(int wait_reqd)
if (_sigq_check_reqd != 0) {
/* Reset flag before handling queued signals: */
_sigq_check_reqd = 0;
-
- dequeue_signals();
+ _dequeue_signals();
}
/*
@@ -809,8 +820,7 @@ thread_kern_poll(int wait_reqd)
if (_sigq_check_reqd != 0) {
/* Reset flag before handling signals: */
_sigq_check_reqd = 0;
-
- dequeue_signals();
+ _dequeue_signals();
}
}
@@ -943,10 +953,7 @@ thread_kern_poll(int wait_reqd)
/* Protect the scheduling queues: */
_queue_signals = 1;
-
- dequeue_signals();
-
- /* Unprotect the scheduling queues: */
+ _dequeue_signals();
_queue_signals = 0;
}
}
@@ -958,6 +965,8 @@ _thread_kern_set_timeout(const struct timespec * timeout)
struct timespec current_time;
struct timeval tv;
+ PTHREAD_TRACE(6);
+
/* Reset the timeout flag for the running thread: */
curthread->timeout = 0;
@@ -998,6 +1007,8 @@ _thread_kern_sig_defer(void)
{
struct pthread *curthread = _get_curthread();
+ PTHREAD_TRACE(7);
+
/* Allow signal deferral to be recursive. */
curthread->sig_defer_count++;
}
@@ -1007,6 +1018,8 @@ _thread_kern_sig_undefer(void)
{
struct pthread *curthread = _get_curthread();
+ PTHREAD_TRACE(8);
+
/*
* Perform checks to yield only if we are about to undefer
* signals.
@@ -1047,12 +1060,14 @@ _thread_kern_sig_undefer(void)
}
}
-static void
-dequeue_signals(void)
+void
+_dequeue_signals(void)
{
char bufr[128];
int i, num;
+ PTHREAD_TRACE(9);
+
/*
* Enter a loop to read and handle queued signals from the
* pthread kernel pipe:
@@ -1072,7 +1087,7 @@ dequeue_signals(void)
}
else {
/* Handle this signal: */
- _thread_sig_handle((int) bufr[i], NULL);
+ _thread_sig_process((int) bufr[i], NULL);
}
}
}
@@ -1085,12 +1100,14 @@ dequeue_signals(void)
}
}
-static inline void
-thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in)
+inline void
+_thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in)
{
pthread_t tid_out = thread_out;
pthread_t tid_in = thread_in;
+ PTHREAD_TRACE(10);
+
if ((tid_out != NULL) &&
(tid_out->flags & PTHREAD_FLAGS_PRIVATE) != 0)
tid_out = NULL;
diff --git a/lib/libc_r/uthread/uthread_kill.c b/lib/libc_r/uthread/uthread_kill.c
index 172d3817513..59d78b80ebf 100644
--- a/lib/libc_r/uthread/uthread_kill.c
+++ b/lib/libc_r/uthread/uthread_kill.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_kill.c,v 1.7 1999/11/25 07:01:37 d Exp $ */
+/* $OpenBSD: uthread_kill.c,v 1.8 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -38,6 +38,12 @@
#include <pthread.h>
#include "pthread_private.h"
+/*
+ * XXX THIS IS WRONG! The signal has to either come through the OS to
+ * get the proper siginfo, context, etc., or we need to gen up a
+ * siginfo (assuming needed). Signal reset and other semantics
+ * also need to be obeyed.
+ */
int
pthread_kill(pthread_t pthread, int sig)
{
@@ -75,7 +81,6 @@ pthread_kill(pthread_t pthread, int sig)
/* Return the signal number: */
pthread->signo = sig;
}
- /* Increment the pending signal count: */
sigaddset(&pthread->sigpend,sig);
break;
@@ -88,7 +93,6 @@ pthread_kill(pthread_t pthread, int sig)
/* Return the signal number: */
pthread->signo = sig;
} else
- /* Increment the pending signal count. */
sigaddset(&pthread->sigpend,sig);
break;
@@ -111,7 +115,6 @@ pthread_kill(pthread_t pthread, int sig)
/* Return the signal number: */
pthread->signo = sig;
} else {
- /* Increment the pending signal count: */
sigaddset(&pthread->sigpend,sig);
}
break;
@@ -144,7 +147,7 @@ pthread_kill(pthread_t pthread, int sig)
/*
* Dispatch the signal via the custom signal
- * handler:
+ * handler: ;;; what about SA_SIGINFO???
*/
(*(_thread_sigact[sig - 1].sa_handler))(sig);
diff --git a/lib/libc_r/uthread/uthread_mutex.c b/lib/libc_r/uthread/uthread_mutex.c
index 41f510c37e4..79bd3573379 100644
--- a/lib/libc_r/uthread/uthread_mutex.c
+++ b/lib/libc_r/uthread/uthread_mutex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_mutex.c,v 1.14 2002/01/23 23:11:57 fgsch Exp $ */
+/* $OpenBSD: uthread_mutex.c,v 1.15 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -715,27 +715,6 @@ pthread_mutex_lock(pthread_mutex_t *mutex)
}
int
-_pthread_mutex_lock(pthread_mutex_t *mutex)
-{
- int ret = 0;
-
- if (_thread_initial == NULL)
- _thread_init();
-
- if (mutex == NULL)
- ret = EINVAL;
-
- /*
- * If the mutex is statically initialized, perform the dynamic
- * initialization marking it private (delete safe):
- */
- else if ((*mutex != NULL) || ((ret = init_static_private(mutex)) == 0))
- ret = mutex_lock_common(mutex);
-
- return (ret);
-}
-
-int
pthread_mutex_unlock(pthread_mutex_t * mutex)
{
return (mutex_unlock_common(mutex, /* add reference */ 0));
diff --git a/lib/libc_r/uthread/uthread_sig.c b/lib/libc_r/uthread/uthread_sig.c
index 48f360f3ea3..be4e5c8323c 100644
--- a/lib/libc_r/uthread/uthread_sig.c
+++ b/lib/libc_r/uthread/uthread_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_sig.c,v 1.13 2002/10/07 22:36:04 marc Exp $ */
+/* $OpenBSD: uthread_sig.c,v 1.14 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -41,10 +41,10 @@
#include "pthread_private.h"
/* Static variables: */
-static spinlock_t signal_lock = _SPINLOCK_INITIALIZER;
-unsigned int pending_sigs[NSIG];
-unsigned int handled_sigs[NSIG];
-int volatile check_pending = 0;
+static _spinlock_lock_t signal_lock = _SPINLOCK_UNLOCKED;
+siginfo_t info_queue[NSIG];
+volatile sig_atomic_t pending_sigs[NSIG];
+volatile sig_atomic_t check_pending = 0;
/* Initialize signal handling facility: */
void
@@ -52,113 +52,142 @@ _thread_sig_init(void)
{
int i;
- /* Clear pending and handled signal counts: */
+ /* Clear local state */
for (i = 1; i < NSIG; i++) {
pending_sigs[i - 1] = 0;
- handled_sigs[i - 1] = 0;
}
/* Clear the lock: */
- signal_lock.access_lock = 0;
+ signal_lock = _SPINLOCK_UNLOCKED;
}
+/*
+ * Process a pending signal unless it is already in progress. If the
+ * SA_NODEFER flag is on, process it any way.
+ */
+void
+_thread_sig_process(int sig, struct sigcontext * scp)
+{
+ int locked = 0;
+
+ if (_atomic_lock(&signal_lock) == 0)
+ locked = 1;
+
+ if (locked || _thread_sigact[sig - 1].sa_flags & SA_NODEFER) {
+ _thread_sig_handle(sig, scp);
+ pending_sigs[sig - 1] = 0;
+ } else
+ check_pending = 1;
+ if (locked)
+ signal_lock = _SPINLOCK_UNLOCKED;
+}
+
+/*
+ * This is the only installed signal handler. In addition to handling
+ * thread kernel signals it is installed in place of application handlers
+ * and dispatches signals appropriately.
+ */
void
-_thread_sig_handler(int sig, int code, struct sigcontext * scp)
+_thread_sig_handler(int sig, siginfo_t *info, struct sigcontext * scp)
{
struct pthread *curthread = _get_curthread();
char c;
int i;
- /* Check if an interval timer signal: */
+ /*
+ * save the info for this signal in a per signal queue of depth
+ * one. Per a POSIX suggestion, only the info for the first
+ * of multiple activations of the same signal is kept.
+ */
+ if (pending_sigs[sig - 1] == 0) {
+ pending_sigs[sig - 1]++;
+ memcpy(&info_queue[sig - 1], info, sizeof *info);
+ }
+
if (sig == _SCHED_SIGNAL) {
/* Update the scheduling clock: */
gettimeofday((struct timeval *)&_sched_tod, NULL);
_sched_ticks++;
- if (_thread_kern_in_sched != 0) {
- /*
- * The scheduler is already running; ignore this
- * signal.
- */
- }
- /*
- * Check if the scheduler interrupt has come when
- * the currently running thread has deferred thread
- * signals.
- */
- else if (curthread->sig_defer_count > 0)
- curthread->yield_on_sig_undefer = 1;
-
- else {
- /*
- * Schedule the next thread. This function is not
- * expected to return because it will do a longjmp
- * instead.
- */
- _thread_kern_sched(scp);
-
- /* The scheduler currently returns here instead
- of calling sigreturn due to a sparc sigreturn
- bug. We should also return. That brings
- us back to the sigtramp code which will
- sigreturn to the context stored on the current
- stack (which is the same as scp, above).
- The code originally did this:
-
- PANIC("Returned to signal function from scheduler");
- */
- return;
- }
- }
- /*
- * Check if the kernel has been interrupted while the scheduler
- * is accessing the scheduling queues or if there is a currently
- * running thread that has deferred signals.
- */
- else if ((_queue_signals != 0) || ((_thread_kern_in_sched == 0) &&
- (curthread->sig_defer_count > 0))) {
- /* Cast the signal number to a character variable: */
- c = sig;
+ /* only process signal when scheduler isn't running */
+ if (_thread_kern_in_sched == 0)
+ if (curthread->sig_defer_count > 0)
+ /*
+ * The scheduler interrupt has come when
+ * the currently running thread has deferred
+ * thread signals.
+ */
+ curthread->yield_on_sig_undefer = 1;
+ else {
+ /* Schedule the next thread. */
+ _thread_kern_sched(scp);
+ /*
+ * The scheduler currently returns here instead
+ * of calling sigreturn due to a sparc sigreturn
+ * bug. We should also return. That brings
+ * us back to the sigtramp code which will
+ * sigreturn to the context stored on the
+ * current stack (which is the same as scp,
+ * above). The code originally did this:
+ *
+ * PANIC("Returned to signal function "
+ * "from scheduler");
+ */
+ return;
+ }
+ } else if ((_queue_signals != 0) ||
+ ((_thread_kern_in_sched == 0) &&
+ (curthread->sig_defer_count > 0))) {
/*
- * Write the signal number to the kernel pipe so that it will
- * be ready to read when this signal handler returns.
+ * The kernel has been interrupted while the scheduler
+ * is accessing the scheduling queues or there is a currently
+ * running thread that has deferred signals.
+ *
+ * Cast the signal number to a character variable and Write
+ * the signal number to the kernel pipe so that it will be
+ * ready to read when this signal handler returns.
*/
+ c = sig;
_thread_sys_write(_thread_kern_pipe[1], &c, 1);
-
- /* Indicate that there are queued signals in the pipe. */
_sigq_check_reqd = 1;
- }
- else {
- if (_atomic_lock(&signal_lock.access_lock)) {
- /* There is another signal handler running: */
- pending_sigs[sig - 1]++;
- check_pending = 1;
+ } else {
+ /* process the signal */
+ _thread_sig_process(sig, scp);
+ /*
+ * process pending signals unless a current signal handler
+ * is running (signal_lock is locked). When locked
+ * the pending signals will be processed when the running
+ * handler returns.
+ */
+ while (check_pending != 0 && _atomic_lock(&signal_lock) == 0) {
+ check_pending = 0;
+ signal_lock = _SPINLOCK_UNLOCKED;
+ for (i = 1; i < NSIG; i++)
+ if (pending_sigs[i - 1])
+ _thread_sig_process(i, scp);
}
- else {
- /* It's safe to handle the signal now. */
- _thread_sig_handle(sig, scp);
+ }
- /* Reset the pending and handled count back to 0: */
- pending_sigs[sig - 1] = 0;
- handled_sigs[sig - 1] = 0;
+}
- signal_lock.access_lock = 0;
- }
+/*
+ * Clear the pending flag for the given signal on all threads
+ */
+void
+_clear_pending_flag(int sig)
+{
+ pthread_t pthread;
- /* Enter a loop to process pending signals: */
- while ((check_pending != 0) &&
- (_atomic_lock(&signal_lock.access_lock) == 0)) {
- check_pending = 0;
- for (i = 1; i < NSIG; i++) {
- if (pending_sigs[i - 1] > handled_sigs[i - 1])
- _thread_sig_handle(i, scp);
- }
- signal_lock.access_lock = 0;
- }
+ TAILQ_FOREACH(pthread, &_thread_list, tle) {
+ sigdelset(&pthread->sigpend, sig);
}
}
+
+/*
+ * Process the given signal.
+ */
void
_thread_sig_handle(int sig, struct sigcontext * scp)
{
@@ -166,51 +195,30 @@ _thread_sig_handle(int sig, struct sigcontext * scp)
int i;
pthread_t pthread, pthread_next;
- /* Check if the signal requires a dump of thread information: */
if (sig == SIGINFO)
- /* Dump thread information to file: */
- _thread_dump_info();
-
- /* Check if an interval timer signal: */
- else if (sig == _SCHED_SIGNAL) {
- /*
- * This shouldn't ever occur (should this panic?).
- */
- } else {
- /* Check if a child has terminated: */
+ _thread_dump_info(); /* Dump thread information */
+ else if (sig == _SCHED_SIGNAL)
+ ; /* This shouldn't ever occur (should this panic?). */
+ else {
if (sig == SIGCHLD) {
/*
* Go through the file list and set all files
* to non-blocking again in case the child
* set some of them to block. Sigh.
*/
- for (i = 0; i < _thread_dtablesize; i++) {
- /* Check if this file is used: */
- if (_thread_fd_table[i] != NULL) {
- /*
- * Set the file descriptor to
- * non-blocking:
- */
+ for (i = 0; i < _thread_dtablesize; i++)
+ if (_thread_fd_table[i] != NULL)
_thread_sys_fcntl(i, F_SETFL,
_thread_fd_table[i]->flags |
O_NONBLOCK);
- }
- }
}
/*
* POSIX says that pending SIGCONT signals are
* discarded when one of these signals occurs.
*/
- if (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU) {
- /*
- * Enter a loop to discard pending SIGCONT
- * signals:
- */
- TAILQ_FOREACH(pthread, &_thread_list, tle) {
- sigdelset(&pthread->sigpend,SIGCONT);
- }
- }
+ if (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
+ _clear_pending_flag(SIGCONT);
/*
* Enter a loop to process each thread in the waiting
@@ -220,7 +228,7 @@ _thread_sig_handle(int sig, struct sigcontext * scp)
* first one we find.
*/
for (pthread = TAILQ_FIRST(&_waitingq);
- pthread != NULL; pthread = pthread_next) {
+ pthread != NULL; pthread = pthread_next) {
/*
* Grab the next thread before possibly destroying
* the link entry.
@@ -243,33 +251,33 @@ _thread_sig_handle(int sig, struct sigcontext * scp)
}
}
- /* Check if the signal is not being ignored: */
- if (_thread_sigact[sig - 1].sa_handler != SIG_IGN)
+ if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
/*
- * Enter a loop to process each thread in the linked
- * list:
+ * mark the signal as pending for each thread
+ * and give the thread a chance to update
+ * its state.
*/
TAILQ_FOREACH(pthread, &_thread_list, tle) {
- pthread_t pthread_saved = curthread;
-
/* Current thread inside critical region? */
if (curthread->sig_defer_count > 0)
pthread->sig_defer_count++;
-
_thread_signal(pthread,sig);
-
- /*
- * Dispatch pending signals to the
- * running thread:
- */
- _set_curthread(pthread);
- _dispatch_signals();
- _set_curthread(pthread_saved);
-
+ if (curthread->sig_defer_count > 0)
+ pthread->sig_defer_count--;
+ }
+ /*
+ * give each thread a chance to dispatch pending
+ * signals.
+ */
+ TAILQ_FOREACH(pthread, &_thread_list, tle) {
/* Current thread inside critical region? */
if (curthread->sig_defer_count > 0)
+ pthread->sig_defer_count++;
+ _dispatch_signals(pthread, scp);
+ if (curthread->sig_defer_count > 0)
pthread->sig_defer_count--;
}
+ }
}
/* Returns nothing. */
@@ -373,11 +381,14 @@ _thread_signal(pthread_t pthread, int sig)
}
}
-/* Dispatch pending signals to the running thread: */
+/*
+ * possibly dispatch a signal to the given thread.
+ */
void
-_dispatch_signals()
+_dispatch_signals(pthread_t pthread, struct sigcontext * scp)
{
- struct pthread *curthread = _get_curthread();
+ pthread_t pthread_saved;
+ struct sigaction act;
void (*action)(int, siginfo_t *, void *);
int i;
@@ -385,7 +396,7 @@ _dispatch_signals()
* Check if there are pending signals for the running
* thread that aren't blocked:
*/
- if ((curthread->sigpend & ~curthread->sigmask) != 0)
+ if ((pthread->sigpend & ~pthread->sigmask) != 0)
/* Look for all possible pending signals: */
for (i = 1; i < NSIG; i++)
/*
@@ -394,23 +405,28 @@ _dispatch_signals()
*/
if (_thread_sigact[i - 1].sa_handler != SIG_DFL &&
_thread_sigact[i - 1].sa_handler != SIG_IGN &&
- sigismember(&curthread->sigpend,i) &&
- !sigismember(&curthread->sigmask,i)) {
+ sigismember(&pthread->sigpend,i) &&
+ !sigismember(&pthread->sigmask,i)) {
action = _thread_sigact[i - 1].sa_sigaction;
-
- /* Clear the pending signal: */
- sigdelset(&curthread->sigpend,i);
+ _clear_pending_flag(i);
/* clear custom handler if SA_RESETHAND set. */
if (_thread_sigact[i - 1].sa_flags &
- SA_RESETHAND)
- _thread_sigact[i - 1].sa_handler =
- SIG_DFL;
+ SA_RESETHAND) {
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = 0;
+ sigemptyset(&act.sa_mask);
+ sigaction(i, &act, NULL);
+ }
+
/*
* Dispatch the signal via the custom signal
- * handler:
+ * handler.
*/
- (*action)(i, 0, 0);
+ pthread_saved = _get_curthread();
+ _set_curthread(pthread);
+ (*action)(i, &info_queue[i - 1], scp);
+ _set_curthread(pthread_saved);
}
}
#endif
diff --git a/lib/libc_r/uthread/uthread_sigaction.c b/lib/libc_r/uthread/uthread_sigaction.c
index de0aaeb7bfe..61463f7ef99 100644
--- a/lib/libc_r/uthread/uthread_sigaction.c
+++ b/lib/libc_r/uthread/uthread_sigaction.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_sigaction.c,v 1.5 1999/11/25 07:01:44 d Exp $ */
+/* $OpenBSD: uthread_sigaction.c,v 1.6 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -75,12 +75,9 @@ sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
*/
if (act != NULL && sig != _SCHED_SIGNAL && sig != SIGCHLD &&
sig != SIGINFO) {
- /* Initialise the global signal action structure: */
gact.sa_mask = act->sa_mask;
- gact.sa_flags = 0;
-
- /* Ensure the scheduling signal is masked: */
sigaddset(&gact.sa_mask, _SCHED_SIGNAL);
+ gact.sa_flags = act->sa_flags | SA_SIGINFO;
/*
* Check if the signal handler is being set to
@@ -91,14 +88,12 @@ sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
/* Specify the built in handler: */
gact.sa_handler = act->sa_handler;
else
- /*
- * Specify the thread kernel signal
- * handler:
- */
- gact.sa_handler = (void (*) ()) _thread_sig_handler;
+ /* Specify the thread kernel signal handler */
+ gact.sa_handler =
+ (void (*) ()) _thread_sig_handler;
/* Change the signal action in the kernel: */
- if (_thread_sys_sigaction(sig,&gact,NULL) != 0)
+ if (_thread_sys_sigaction(sig, &gact, NULL) != 0)
ret = -1;
}
}
diff --git a/lib/libc_r/uthread/uthread_signal.c b/lib/libc_r/uthread/uthread_signal.c
index bd9b488b3d0..3cc2373fc64 100644
--- a/lib/libc_r/uthread/uthread_signal.c
+++ b/lib/libc_r/uthread/uthread_signal.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_signal.c,v 1.4 1999/11/25 07:01:45 d Exp $ */
+/* $OpenBSD: uthread_signal.c,v 1.5 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -46,7 +46,7 @@ _thread_sys_signal(int s, sig_t a)
/* Initialise the signal action structure: */
sigemptyset(&sa.sa_mask);
sa.sa_handler = a;
- sa.sa_flags = 0;
+ sa.sa_flags = SA_SIGINFO;
/* Perform the sigaction syscall: */
if (_thread_sys_sigaction(s, &sa, &osa) < 0) {
diff --git a/lib/libc_r/uthread/uthread_sigwait.c b/lib/libc_r/uthread/uthread_sigwait.c
index 0d1bf618be1..b7b72c7ea09 100644
--- a/lib/libc_r/uthread/uthread_sigwait.c
+++ b/lib/libc_r/uthread/uthread_sigwait.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_sigwait.c,v 1.10 2002/02/21 20:57:41 fgsch Exp $ */
+/* $OpenBSD: uthread_sigwait.c,v 1.11 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -53,7 +53,7 @@ sigwait(const sigset_t * set, int *sig)
* Specify the thread kernel signal handler.
*/
act.sa_handler = (void (*) ()) _thread_sig_handler;
- act.sa_flags = SA_RESTART;
+ act.sa_flags = SA_SIGINFO | SA_RESTART;
/* Ensure the signal handler cannot be interrupted by other signals: */
sigfillset(&act.sa_mask);
diff --git a/lib/libpthread/uthread/pthread_private.h b/lib/libpthread/uthread/pthread_private.h
index 23723ca68e0..88341872451 100644
--- a/lib/libpthread/uthread/pthread_private.h
+++ b/lib/libpthread/uthread/pthread_private.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pthread_private.h,v 1.35 2002/02/21 20:57:41 fgsch Exp $ */
+/* $OpenBSD: pthread_private.h,v 1.36 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -1082,8 +1082,9 @@ __BEGIN_DECLS
int _find_thread(pthread_t);
struct pthread *_get_curthread(void);
void _set_curthread(struct pthread *);
-int _thread_create(pthread_t *,const pthread_attr_t *,void *(*start_routine)(void *),void *,pthread_t);
-void _dispatch_signals(void);
+int _thread_create(pthread_t *, const pthread_attr_t *,
+ void *(*start_routine)(void *), void *,pthread_t);
+void _dispatch_signals(pthread_t, struct sigcontext *);
void _thread_signal(pthread_t, int);
int _mutex_cv_lock(pthread_mutex_t *);
int _mutex_cv_unlock(pthread_mutex_t *);
@@ -1115,9 +1116,10 @@ void _thread_kern_sched_state_unlock(enum pthread_state state,
void _thread_kern_set_timeout(const struct timespec *);
void _thread_kern_sig_defer(void);
void _thread_kern_sig_undefer(void);
-void _thread_sig_handler(int, int, struct sigcontext *);
+void _thread_sig_handler(int, siginfo_t *, struct sigcontext *);
void _thread_sig_handle(int, struct sigcontext *);
void _thread_sig_init(void);
+void _thread_sig_process(int, struct sigcontext *);
void _thread_start(void);
void _thread_start_sig_handler(void);
void _thread_seterrno(pthread_t,int);
diff --git a/lib/libpthread/uthread/uthread_accept.c b/lib/libpthread/uthread/uthread_accept.c
index 23197f8dadc..9c4b1d81eca 100644
--- a/lib/libpthread/uthread/uthread_accept.c
+++ b/lib/libpthread/uthread/uthread_accept.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_accept.c,v 1.5 2001/08/21 19:24:53 fgsch Exp $ */
+/* $OpenBSD: uthread_accept.c,v 1.6 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -52,7 +52,8 @@ accept(int fd, struct sockaddr * name, socklen_t *namelen)
/* Enter a loop to wait for a connection request: */
while ((ret = _thread_sys_accept(fd, name, namelen)) < 0) {
/* Check if the socket is to block: */
- if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
/* Save the socket file descriptor: */
curthread->data.fd.fd = fd;
curthread->data.fd.fname = __FILE__;
@@ -63,7 +64,8 @@ accept(int fd, struct sockaddr * name, socklen_t *namelen)
curthread->interrupted = 0;
/* Schedule the next thread: */
- _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__);
+ _thread_kern_sched_state(PS_FDR_WAIT, __FILE__,
+ __LINE__);
/* Check if the wait was interrupted: */
if (curthread->interrupted) {
@@ -81,26 +83,19 @@ accept(int fd, struct sockaddr * name, socklen_t *namelen)
}
}
- /* Check for errors: */
- if (ret < 0) {
- }
- /* Initialise the file descriptor table for the new socket: */
- else if (_thread_fd_table_init(ret) != 0) {
- /* Quietly close the socket: */
- _thread_sys_close(ret);
-
- /* Return an error: */
- ret = -1;
- }
- /*
- * If the parent socket was blocking, make sure that
- * the new socket is also set blocking here (as the
- * call to _thread_fd_table_init() above will always
- * set the new socket flags to non-blocking, as that
- * will be the inherited state of the new socket.
+ /*
+ * If no errors initialize the file descriptor table
+ * for the new socket. Turn on blocking mode in the
+ * child if it is on in the parent. This is done
+ * as _thread_fd_table_init *may* have turned the flag on.
*/
- if((ret > 0) && (_thread_fd_table[fd]->flags & O_NONBLOCK) == 0)
- _thread_fd_table[ret]->flags &= ~O_NONBLOCK;
+ if (ret != -1)
+ if (_thread_fd_table_init(ret) != 0) {
+ /* Quietly close the socket: */
+ _thread_sys_close(ret);
+ ret = -1;
+ } else if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0)
+ _thread_fd_table[ret]->flags &= ~O_NONBLOCK;
/* Unlock the file descriptor: */
_FD_UNLOCK(fd, FD_RDWR);
diff --git a/lib/libpthread/uthread/uthread_exit.c b/lib/libpthread/uthread/uthread_exit.c
index a7a0c60a267..27ed0903ea6 100644
--- a/lib/libpthread/uthread/uthread_exit.c
+++ b/lib/libpthread/uthread/uthread_exit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_exit.c,v 1.15 2001/12/19 02:02:52 fgsch Exp $ */
+/* $OpenBSD: uthread_exit.c,v 1.16 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -132,7 +132,7 @@ _thread_exit(const char *fname, int lineno, const char *string)
/* Set the abort handler to default (dump core) */
sa.sa_handler = SIG_DFL;
sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
+ sa.sa_flags = SA_SIGINFO;
(void)_thread_sys_sigaction(SIGABRT, &sa, NULL);
(void)_thread_sys_kill(_thread_sys_getpid(), SIGABRT);
for (;;) ;
diff --git a/lib/libpthread/uthread/uthread_init.c b/lib/libpthread/uthread/uthread_init.c
index d9f398c381b..803e46e1fe8 100644
--- a/lib/libpthread/uthread/uthread_init.c
+++ b/lib/libpthread/uthread/uthread_init.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_init.c,v 1.21 2002/02/21 20:57:41 fgsch Exp $ */
+/* $OpenBSD: uthread_init.c,v 1.22 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -222,7 +222,7 @@ _thread_init(void)
/* Initialise the global signal action structure: */
sigfillset(&act.sa_mask);
act.sa_handler = (void (*) ()) _thread_sig_handler;
- act.sa_flags = 0;
+ act.sa_flags = SA_SIGINFO;
/* Clear pending signals for the process: */
sigemptyset(&_process_sigpending);
@@ -263,6 +263,9 @@ _thread_init(void)
*/
PANIC("Cannot initialize signal handler");
}
+ _thread_sigact[_SCHED_SIGNAL - 1].sa_flags = SA_SIGINFO;
+ _thread_sigact[SIGINFO - 1].sa_flags = SA_SIGINFO;
+ _thread_sigact[SIGCHLD - 1].sa_flags = SA_SIGINFO;
/* Get the process signal mask: */
_thread_sys_sigprocmask(SIG_SETMASK, NULL, &_process_sigmask);
diff --git a/lib/libpthread/uthread/uthread_kern.c b/lib/libpthread/uthread/uthread_kern.c
index da3c91ff933..f7db1f0871b 100644
--- a/lib/libpthread/uthread/uthread_kern.c
+++ b/lib/libpthread/uthread/uthread_kern.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_kern.c,v 1.21 2002/02/21 20:57:41 fgsch Exp $ */
+/* $OpenBSD: uthread_kern.c,v 1.22 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -50,15 +50,19 @@
#include <pthread.h>
#include "pthread_private.h"
-/* Static function prototype definitions: */
-static void
-thread_kern_poll(int wait_reqd);
-
-static void
-dequeue_signals(void);
+#if defined(PTHREAD_TRACE_KERN)
+#define PTHREAD_TRACE(x) _thread_sys_write(-1, (void*) x, 0)
+#else
+#define PTHREAD_TRACE(x)
+#endif
-static inline void
-thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in);
+/*
+ * local functions. Do NOT make these static... we want so see them in
+ * crash dumps.
+ */
+void _thread_kern_poll(int);
+void _dequeue_signals(void);
+inline void _thread_run_switch_hook(pthread_t, pthread_t);
/* Static variables: */
static int last_tick = 0;
@@ -68,6 +72,7 @@ _thread_kern_sched_sig(void)
{
struct pthread *curthread = _get_curthread();
+ PTHREAD_TRACE(1);
curthread->check_pending = 1;
_thread_kern_sched(NULL);
}
@@ -83,6 +88,8 @@ _thread_kern_sched(struct sigcontext * scp)
int add_to_prioq;
pthread_t old_thread_run;
+ PTHREAD_TRACE(2);
+
/*
* Flag the pthread kernel as executing scheduler code
* to avoid a scheduler signal from interrupting this
@@ -291,7 +298,7 @@ _thread_kern_sched(struct sigcontext * scp)
* Poll file descriptors to update the state of threads
* waiting on file I/O where data may be available:
*/
- thread_kern_poll(0);
+ _thread_kern_poll(0);
/* Protect the scheduling queues: */
_queue_signals = 1;
@@ -409,7 +416,7 @@ _thread_kern_sched(struct sigcontext * scp)
* There are no threads ready to run, so wait until
* something happens that changes this condition:
*/
- thread_kern_poll(1);
+ _thread_kern_poll(1);
/*
* This process' usage will likely be very small
@@ -445,7 +452,7 @@ _thread_kern_sched(struct sigcontext * scp)
/* Protect the scheduling queues again: */
_queue_signals = 1;
- dequeue_signals();
+ _dequeue_signals();
/*
* Check for a higher priority thread that
@@ -519,7 +526,7 @@ _thread_kern_sched(struct sigcontext * scp)
*/
if ((_sched_switch_hook != NULL) &&
(_last_user_thread != curthread)) {
- thread_run_switch_hook(_last_user_thread,
+ _thread_run_switch_hook(_last_user_thread,
curthread);
}
@@ -543,7 +550,7 @@ _thread_kern_sched(struct sigcontext * scp)
if (_sched_switch_hook != NULL) {
/* Run the installed switch hook: */
- thread_run_switch_hook(_last_user_thread,
+ _thread_run_switch_hook(_last_user_thread,
curthread);
}
@@ -569,6 +576,7 @@ _thread_kern_sched_state(enum pthread_state state, char *fname, int lineno)
{
struct pthread *curthread = _get_curthread();
+ PTHREAD_TRACE(3);
/*
* Flag the pthread kernel as executing scheduler code
* to avoid a scheduler signal from interrupting this
@@ -597,6 +605,8 @@ _thread_kern_sched_state_unlock(enum pthread_state state,
{
struct pthread *curthread = _get_curthread();
+ PTHREAD_TRACE(4);
+
/*
* Flag the pthread kernel as executing scheduler code
* to avoid a scheduler signal from interrupting this
@@ -622,8 +632,8 @@ _thread_kern_sched_state_unlock(enum pthread_state state,
_thread_kern_sched(NULL);
}
-static void
-thread_kern_poll(int wait_reqd)
+void
+_thread_kern_poll(int wait_reqd)
{
int count = 0;
int i, found;
@@ -634,6 +644,8 @@ thread_kern_poll(int wait_reqd)
struct timespec ts;
struct timeval tv;
+ PTHREAD_TRACE(5);
+
/* Check if the caller wants to wait: */
if (wait_reqd == 0) {
timeout_ms = 0;
@@ -683,8 +695,7 @@ thread_kern_poll(int wait_reqd)
if (_sigq_check_reqd != 0) {
/* Reset flag before handling queued signals: */
_sigq_check_reqd = 0;
-
- dequeue_signals();
+ _dequeue_signals();
}
/*
@@ -809,8 +820,7 @@ thread_kern_poll(int wait_reqd)
if (_sigq_check_reqd != 0) {
/* Reset flag before handling signals: */
_sigq_check_reqd = 0;
-
- dequeue_signals();
+ _dequeue_signals();
}
}
@@ -943,10 +953,7 @@ thread_kern_poll(int wait_reqd)
/* Protect the scheduling queues: */
_queue_signals = 1;
-
- dequeue_signals();
-
- /* Unprotect the scheduling queues: */
+ _dequeue_signals();
_queue_signals = 0;
}
}
@@ -958,6 +965,8 @@ _thread_kern_set_timeout(const struct timespec * timeout)
struct timespec current_time;
struct timeval tv;
+ PTHREAD_TRACE(6);
+
/* Reset the timeout flag for the running thread: */
curthread->timeout = 0;
@@ -998,6 +1007,8 @@ _thread_kern_sig_defer(void)
{
struct pthread *curthread = _get_curthread();
+ PTHREAD_TRACE(7);
+
/* Allow signal deferral to be recursive. */
curthread->sig_defer_count++;
}
@@ -1007,6 +1018,8 @@ _thread_kern_sig_undefer(void)
{
struct pthread *curthread = _get_curthread();
+ PTHREAD_TRACE(8);
+
/*
* Perform checks to yield only if we are about to undefer
* signals.
@@ -1047,12 +1060,14 @@ _thread_kern_sig_undefer(void)
}
}
-static void
-dequeue_signals(void)
+void
+_dequeue_signals(void)
{
char bufr[128];
int i, num;
+ PTHREAD_TRACE(9);
+
/*
* Enter a loop to read and handle queued signals from the
* pthread kernel pipe:
@@ -1072,7 +1087,7 @@ dequeue_signals(void)
}
else {
/* Handle this signal: */
- _thread_sig_handle((int) bufr[i], NULL);
+ _thread_sig_process((int) bufr[i], NULL);
}
}
}
@@ -1085,12 +1100,14 @@ dequeue_signals(void)
}
}
-static inline void
-thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in)
+inline void
+_thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in)
{
pthread_t tid_out = thread_out;
pthread_t tid_in = thread_in;
+ PTHREAD_TRACE(10);
+
if ((tid_out != NULL) &&
(tid_out->flags & PTHREAD_FLAGS_PRIVATE) != 0)
tid_out = NULL;
diff --git a/lib/libpthread/uthread/uthread_kill.c b/lib/libpthread/uthread/uthread_kill.c
index 172d3817513..59d78b80ebf 100644
--- a/lib/libpthread/uthread/uthread_kill.c
+++ b/lib/libpthread/uthread/uthread_kill.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_kill.c,v 1.7 1999/11/25 07:01:37 d Exp $ */
+/* $OpenBSD: uthread_kill.c,v 1.8 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -38,6 +38,12 @@
#include <pthread.h>
#include "pthread_private.h"
+/*
+ * XXX THIS IS WRONG! The signal has to either come through the OS to
+ * get the proper siginfo, context, etc., or we need to gen up a
+ * siginfo (assuming needed). Signal reset and other semantics
+ * also need to be obeyed.
+ */
int
pthread_kill(pthread_t pthread, int sig)
{
@@ -75,7 +81,6 @@ pthread_kill(pthread_t pthread, int sig)
/* Return the signal number: */
pthread->signo = sig;
}
- /* Increment the pending signal count: */
sigaddset(&pthread->sigpend,sig);
break;
@@ -88,7 +93,6 @@ pthread_kill(pthread_t pthread, int sig)
/* Return the signal number: */
pthread->signo = sig;
} else
- /* Increment the pending signal count. */
sigaddset(&pthread->sigpend,sig);
break;
@@ -111,7 +115,6 @@ pthread_kill(pthread_t pthread, int sig)
/* Return the signal number: */
pthread->signo = sig;
} else {
- /* Increment the pending signal count: */
sigaddset(&pthread->sigpend,sig);
}
break;
@@ -144,7 +147,7 @@ pthread_kill(pthread_t pthread, int sig)
/*
* Dispatch the signal via the custom signal
- * handler:
+ * handler: ;;; what about SA_SIGINFO???
*/
(*(_thread_sigact[sig - 1].sa_handler))(sig);
diff --git a/lib/libpthread/uthread/uthread_mutex.c b/lib/libpthread/uthread/uthread_mutex.c
index 41f510c37e4..79bd3573379 100644
--- a/lib/libpthread/uthread/uthread_mutex.c
+++ b/lib/libpthread/uthread/uthread_mutex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_mutex.c,v 1.14 2002/01/23 23:11:57 fgsch Exp $ */
+/* $OpenBSD: uthread_mutex.c,v 1.15 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -715,27 +715,6 @@ pthread_mutex_lock(pthread_mutex_t *mutex)
}
int
-_pthread_mutex_lock(pthread_mutex_t *mutex)
-{
- int ret = 0;
-
- if (_thread_initial == NULL)
- _thread_init();
-
- if (mutex == NULL)
- ret = EINVAL;
-
- /*
- * If the mutex is statically initialized, perform the dynamic
- * initialization marking it private (delete safe):
- */
- else if ((*mutex != NULL) || ((ret = init_static_private(mutex)) == 0))
- ret = mutex_lock_common(mutex);
-
- return (ret);
-}
-
-int
pthread_mutex_unlock(pthread_mutex_t * mutex)
{
return (mutex_unlock_common(mutex, /* add reference */ 0));
diff --git a/lib/libpthread/uthread/uthread_sig.c b/lib/libpthread/uthread/uthread_sig.c
index 48f360f3ea3..be4e5c8323c 100644
--- a/lib/libpthread/uthread/uthread_sig.c
+++ b/lib/libpthread/uthread/uthread_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_sig.c,v 1.13 2002/10/07 22:36:04 marc Exp $ */
+/* $OpenBSD: uthread_sig.c,v 1.14 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -41,10 +41,10 @@
#include "pthread_private.h"
/* Static variables: */
-static spinlock_t signal_lock = _SPINLOCK_INITIALIZER;
-unsigned int pending_sigs[NSIG];
-unsigned int handled_sigs[NSIG];
-int volatile check_pending = 0;
+static _spinlock_lock_t signal_lock = _SPINLOCK_UNLOCKED;
+siginfo_t info_queue[NSIG];
+volatile sig_atomic_t pending_sigs[NSIG];
+volatile sig_atomic_t check_pending = 0;
/* Initialize signal handling facility: */
void
@@ -52,113 +52,142 @@ _thread_sig_init(void)
{
int i;
- /* Clear pending and handled signal counts: */
+ /* Clear local state */
for (i = 1; i < NSIG; i++) {
pending_sigs[i - 1] = 0;
- handled_sigs[i - 1] = 0;
}
/* Clear the lock: */
- signal_lock.access_lock = 0;
+ signal_lock = _SPINLOCK_UNLOCKED;
}
+/*
+ * Process a pending signal unless it is already in progress. If the
+ * SA_NODEFER flag is on, process it any way.
+ */
+void
+_thread_sig_process(int sig, struct sigcontext * scp)
+{
+ int locked = 0;
+
+ if (_atomic_lock(&signal_lock) == 0)
+ locked = 1;
+
+ if (locked || _thread_sigact[sig - 1].sa_flags & SA_NODEFER) {
+ _thread_sig_handle(sig, scp);
+ pending_sigs[sig - 1] = 0;
+ } else
+ check_pending = 1;
+ if (locked)
+ signal_lock = _SPINLOCK_UNLOCKED;
+}
+
+/*
+ * This is the only installed signal handler. In addition to handling
+ * thread kernel signals it is installed in place of application handlers
+ * and dispatches signals appropriately.
+ */
void
-_thread_sig_handler(int sig, int code, struct sigcontext * scp)
+_thread_sig_handler(int sig, siginfo_t *info, struct sigcontext * scp)
{
struct pthread *curthread = _get_curthread();
char c;
int i;
- /* Check if an interval timer signal: */
+ /*
+ * save the info for this signal in a per signal queue of depth
+ * one. Per a POSIX suggestion, only the info for the first
+ * of multiple activations of the same signal is kept.
+ */
+ if (pending_sigs[sig - 1] == 0) {
+ pending_sigs[sig - 1]++;
+ memcpy(&info_queue[sig - 1], info, sizeof *info);
+ }
+
if (sig == _SCHED_SIGNAL) {
/* Update the scheduling clock: */
gettimeofday((struct timeval *)&_sched_tod, NULL);
_sched_ticks++;
- if (_thread_kern_in_sched != 0) {
- /*
- * The scheduler is already running; ignore this
- * signal.
- */
- }
- /*
- * Check if the scheduler interrupt has come when
- * the currently running thread has deferred thread
- * signals.
- */
- else if (curthread->sig_defer_count > 0)
- curthread->yield_on_sig_undefer = 1;
-
- else {
- /*
- * Schedule the next thread. This function is not
- * expected to return because it will do a longjmp
- * instead.
- */
- _thread_kern_sched(scp);
-
- /* The scheduler currently returns here instead
- of calling sigreturn due to a sparc sigreturn
- bug. We should also return. That brings
- us back to the sigtramp code which will
- sigreturn to the context stored on the current
- stack (which is the same as scp, above).
- The code originally did this:
-
- PANIC("Returned to signal function from scheduler");
- */
- return;
- }
- }
- /*
- * Check if the kernel has been interrupted while the scheduler
- * is accessing the scheduling queues or if there is a currently
- * running thread that has deferred signals.
- */
- else if ((_queue_signals != 0) || ((_thread_kern_in_sched == 0) &&
- (curthread->sig_defer_count > 0))) {
- /* Cast the signal number to a character variable: */
- c = sig;
+ /* only process signal when scheduler isn't running */
+ if (_thread_kern_in_sched == 0)
+ if (curthread->sig_defer_count > 0)
+ /*
+ * The scheduler interrupt has come when
+ * the currently running thread has deferred
+ * thread signals.
+ */
+ curthread->yield_on_sig_undefer = 1;
+ else {
+ /* Schedule the next thread. */
+ _thread_kern_sched(scp);
+ /*
+ * The scheduler currently returns here instead
+ * of calling sigreturn due to a sparc sigreturn
+ * bug. We should also return. That brings
+ * us back to the sigtramp code which will
+ * sigreturn to the context stored on the
+ * current stack (which is the same as scp,
+ * above). The code originally did this:
+ *
+ * PANIC("Returned to signal function "
+ * "from scheduler");
+ */
+ return;
+ }
+ } else if ((_queue_signals != 0) ||
+ ((_thread_kern_in_sched == 0) &&
+ (curthread->sig_defer_count > 0))) {
/*
- * Write the signal number to the kernel pipe so that it will
- * be ready to read when this signal handler returns.
+ * The kernel has been interrupted while the scheduler
+ * is accessing the scheduling queues or there is a currently
+ * running thread that has deferred signals.
+ *
+ * Cast the signal number to a character variable and Write
+ * the signal number to the kernel pipe so that it will be
+ * ready to read when this signal handler returns.
*/
+ c = sig;
_thread_sys_write(_thread_kern_pipe[1], &c, 1);
-
- /* Indicate that there are queued signals in the pipe. */
_sigq_check_reqd = 1;
- }
- else {
- if (_atomic_lock(&signal_lock.access_lock)) {
- /* There is another signal handler running: */
- pending_sigs[sig - 1]++;
- check_pending = 1;
+ } else {
+ /* process the signal */
+ _thread_sig_process(sig, scp);
+ /*
+ * process pending signals unless a current signal handler
+ * is running (signal_lock is locked). When locked
+ * the pending signals will be processed when the running
+ * handler returns.
+ */
+ while (check_pending != 0 && _atomic_lock(&signal_lock) == 0) {
+ check_pending = 0;
+ signal_lock = _SPINLOCK_UNLOCKED;
+ for (i = 1; i < NSIG; i++)
+ if (pending_sigs[i - 1])
+ _thread_sig_process(i, scp);
}
- else {
- /* It's safe to handle the signal now. */
- _thread_sig_handle(sig, scp);
+ }
- /* Reset the pending and handled count back to 0: */
- pending_sigs[sig - 1] = 0;
- handled_sigs[sig - 1] = 0;
+}
- signal_lock.access_lock = 0;
- }
+/*
+ * Clear the pending flag for the given signal on all threads
+ */
+void
+_clear_pending_flag(int sig)
+{
+ pthread_t pthread;
- /* Enter a loop to process pending signals: */
- while ((check_pending != 0) &&
- (_atomic_lock(&signal_lock.access_lock) == 0)) {
- check_pending = 0;
- for (i = 1; i < NSIG; i++) {
- if (pending_sigs[i - 1] > handled_sigs[i - 1])
- _thread_sig_handle(i, scp);
- }
- signal_lock.access_lock = 0;
- }
+ TAILQ_FOREACH(pthread, &_thread_list, tle) {
+ sigdelset(&pthread->sigpend, sig);
}
}
+
+/*
+ * Process the given signal.
+ */
void
_thread_sig_handle(int sig, struct sigcontext * scp)
{
@@ -166,51 +195,30 @@ _thread_sig_handle(int sig, struct sigcontext * scp)
int i;
pthread_t pthread, pthread_next;
- /* Check if the signal requires a dump of thread information: */
if (sig == SIGINFO)
- /* Dump thread information to file: */
- _thread_dump_info();
-
- /* Check if an interval timer signal: */
- else if (sig == _SCHED_SIGNAL) {
- /*
- * This shouldn't ever occur (should this panic?).
- */
- } else {
- /* Check if a child has terminated: */
+ _thread_dump_info(); /* Dump thread information */
+ else if (sig == _SCHED_SIGNAL)
+ ; /* This shouldn't ever occur (should this panic?). */
+ else {
if (sig == SIGCHLD) {
/*
* Go through the file list and set all files
* to non-blocking again in case the child
* set some of them to block. Sigh.
*/
- for (i = 0; i < _thread_dtablesize; i++) {
- /* Check if this file is used: */
- if (_thread_fd_table[i] != NULL) {
- /*
- * Set the file descriptor to
- * non-blocking:
- */
+ for (i = 0; i < _thread_dtablesize; i++)
+ if (_thread_fd_table[i] != NULL)
_thread_sys_fcntl(i, F_SETFL,
_thread_fd_table[i]->flags |
O_NONBLOCK);
- }
- }
}
/*
* POSIX says that pending SIGCONT signals are
* discarded when one of these signals occurs.
*/
- if (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU) {
- /*
- * Enter a loop to discard pending SIGCONT
- * signals:
- */
- TAILQ_FOREACH(pthread, &_thread_list, tle) {
- sigdelset(&pthread->sigpend,SIGCONT);
- }
- }
+ if (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
+ _clear_pending_flag(SIGCONT);
/*
* Enter a loop to process each thread in the waiting
@@ -220,7 +228,7 @@ _thread_sig_handle(int sig, struct sigcontext * scp)
* first one we find.
*/
for (pthread = TAILQ_FIRST(&_waitingq);
- pthread != NULL; pthread = pthread_next) {
+ pthread != NULL; pthread = pthread_next) {
/*
* Grab the next thread before possibly destroying
* the link entry.
@@ -243,33 +251,33 @@ _thread_sig_handle(int sig, struct sigcontext * scp)
}
}
- /* Check if the signal is not being ignored: */
- if (_thread_sigact[sig - 1].sa_handler != SIG_IGN)
+ if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
/*
- * Enter a loop to process each thread in the linked
- * list:
+ * mark the signal as pending for each thread
+ * and give the thread a chance to update
+ * its state.
*/
TAILQ_FOREACH(pthread, &_thread_list, tle) {
- pthread_t pthread_saved = curthread;
-
/* Current thread inside critical region? */
if (curthread->sig_defer_count > 0)
pthread->sig_defer_count++;
-
_thread_signal(pthread,sig);
-
- /*
- * Dispatch pending signals to the
- * running thread:
- */
- _set_curthread(pthread);
- _dispatch_signals();
- _set_curthread(pthread_saved);
-
+ if (curthread->sig_defer_count > 0)
+ pthread->sig_defer_count--;
+ }
+ /*
+ * give each thread a chance to dispatch pending
+ * signals.
+ */
+ TAILQ_FOREACH(pthread, &_thread_list, tle) {
/* Current thread inside critical region? */
if (curthread->sig_defer_count > 0)
+ pthread->sig_defer_count++;
+ _dispatch_signals(pthread, scp);
+ if (curthread->sig_defer_count > 0)
pthread->sig_defer_count--;
}
+ }
}
/* Returns nothing. */
@@ -373,11 +381,14 @@ _thread_signal(pthread_t pthread, int sig)
}
}
-/* Dispatch pending signals to the running thread: */
+/*
+ * possibly dispatch a signal to the given thread.
+ */
void
-_dispatch_signals()
+_dispatch_signals(pthread_t pthread, struct sigcontext * scp)
{
- struct pthread *curthread = _get_curthread();
+ pthread_t pthread_saved;
+ struct sigaction act;
void (*action)(int, siginfo_t *, void *);
int i;
@@ -385,7 +396,7 @@ _dispatch_signals()
* Check if there are pending signals for the running
* thread that aren't blocked:
*/
- if ((curthread->sigpend & ~curthread->sigmask) != 0)
+ if ((pthread->sigpend & ~pthread->sigmask) != 0)
/* Look for all possible pending signals: */
for (i = 1; i < NSIG; i++)
/*
@@ -394,23 +405,28 @@ _dispatch_signals()
*/
if (_thread_sigact[i - 1].sa_handler != SIG_DFL &&
_thread_sigact[i - 1].sa_handler != SIG_IGN &&
- sigismember(&curthread->sigpend,i) &&
- !sigismember(&curthread->sigmask,i)) {
+ sigismember(&pthread->sigpend,i) &&
+ !sigismember(&pthread->sigmask,i)) {
action = _thread_sigact[i - 1].sa_sigaction;
-
- /* Clear the pending signal: */
- sigdelset(&curthread->sigpend,i);
+ _clear_pending_flag(i);
/* clear custom handler if SA_RESETHAND set. */
if (_thread_sigact[i - 1].sa_flags &
- SA_RESETHAND)
- _thread_sigact[i - 1].sa_handler =
- SIG_DFL;
+ SA_RESETHAND) {
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = 0;
+ sigemptyset(&act.sa_mask);
+ sigaction(i, &act, NULL);
+ }
+
/*
* Dispatch the signal via the custom signal
- * handler:
+ * handler.
*/
- (*action)(i, 0, 0);
+ pthread_saved = _get_curthread();
+ _set_curthread(pthread);
+ (*action)(i, &info_queue[i - 1], scp);
+ _set_curthread(pthread_saved);
}
}
#endif
diff --git a/lib/libpthread/uthread/uthread_sigaction.c b/lib/libpthread/uthread/uthread_sigaction.c
index de0aaeb7bfe..61463f7ef99 100644
--- a/lib/libpthread/uthread/uthread_sigaction.c
+++ b/lib/libpthread/uthread/uthread_sigaction.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_sigaction.c,v 1.5 1999/11/25 07:01:44 d Exp $ */
+/* $OpenBSD: uthread_sigaction.c,v 1.6 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -75,12 +75,9 @@ sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
*/
if (act != NULL && sig != _SCHED_SIGNAL && sig != SIGCHLD &&
sig != SIGINFO) {
- /* Initialise the global signal action structure: */
gact.sa_mask = act->sa_mask;
- gact.sa_flags = 0;
-
- /* Ensure the scheduling signal is masked: */
sigaddset(&gact.sa_mask, _SCHED_SIGNAL);
+ gact.sa_flags = act->sa_flags | SA_SIGINFO;
/*
* Check if the signal handler is being set to
@@ -91,14 +88,12 @@ sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
/* Specify the built in handler: */
gact.sa_handler = act->sa_handler;
else
- /*
- * Specify the thread kernel signal
- * handler:
- */
- gact.sa_handler = (void (*) ()) _thread_sig_handler;
+ /* Specify the thread kernel signal handler */
+ gact.sa_handler =
+ (void (*) ()) _thread_sig_handler;
/* Change the signal action in the kernel: */
- if (_thread_sys_sigaction(sig,&gact,NULL) != 0)
+ if (_thread_sys_sigaction(sig, &gact, NULL) != 0)
ret = -1;
}
}
diff --git a/lib/libpthread/uthread/uthread_signal.c b/lib/libpthread/uthread/uthread_signal.c
index bd9b488b3d0..3cc2373fc64 100644
--- a/lib/libpthread/uthread/uthread_signal.c
+++ b/lib/libpthread/uthread/uthread_signal.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_signal.c,v 1.4 1999/11/25 07:01:45 d Exp $ */
+/* $OpenBSD: uthread_signal.c,v 1.5 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -46,7 +46,7 @@ _thread_sys_signal(int s, sig_t a)
/* Initialise the signal action structure: */
sigemptyset(&sa.sa_mask);
sa.sa_handler = a;
- sa.sa_flags = 0;
+ sa.sa_flags = SA_SIGINFO;
/* Perform the sigaction syscall: */
if (_thread_sys_sigaction(s, &sa, &osa) < 0) {
diff --git a/lib/libpthread/uthread/uthread_sigwait.c b/lib/libpthread/uthread/uthread_sigwait.c
index 0d1bf618be1..b7b72c7ea09 100644
--- a/lib/libpthread/uthread/uthread_sigwait.c
+++ b/lib/libpthread/uthread/uthread_sigwait.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_sigwait.c,v 1.10 2002/02/21 20:57:41 fgsch Exp $ */
+/* $OpenBSD: uthread_sigwait.c,v 1.11 2002/10/30 19:11:56 marc Exp $ */
/*
* Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -53,7 +53,7 @@ sigwait(const sigset_t * set, int *sig)
* Specify the thread kernel signal handler.
*/
act.sa_handler = (void (*) ()) _thread_sig_handler;
- act.sa_flags = SA_RESTART;
+ act.sa_flags = SA_SIGINFO | SA_RESTART;
/* Ensure the signal handler cannot be interrupted by other signals: */
sigfillset(&act.sa_mask);