1999-01-07 Xavier Leroy <Xavier.Leroy@inria.fr>

* pthread.c: Use a third signal __pthread_sig_debug distinct
	from __pthread_sig_cancel to notify gdb when a thread is
	created
	* manager.c: Likewise.
	* internals.h: Likewise.
	* signals.c: The implementation of sigwait(s) assumed that
	all signals in s have signal handlers already attached.
	This is not required by the standard, so make it work
	also if some of the signals have no handlers.
This commit is contained in:
Ulrich Drepper 1999-01-07 11:53:05 +00:00
parent 3499233817
commit b92ad8d61f
5 changed files with 85 additions and 22 deletions

View file

@ -1,3 +1,15 @@
1999-01-07 Xavier Leroy <Xavier.Leroy@inria.fr>
* pthread.c: Use a third signal __pthread_sig_debug distinct
from __pthread_sig_cancel to notify gdb when a thread is
created
* manager.c: Likewise.
* internals.h: Likewise.
* signals.c: The implementation of sigwait(s) assumed that
all signals in s have signal handlers already attached.
This is not required by the standard, so make it work
also if some of the signals have no handlers.
1999-01-05 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
* linuxthreads.texi: Remove pointers from first @node. Move old

View file

@ -148,6 +148,10 @@ struct pthread_request {
extern int __pthread_sig_restart;
extern int __pthread_sig_cancel;
/* Signal used for interfacing with gdb */
extern int __pthread_sig_debug;
/* Default signals used if we don't have realtime signals */
#define DEFAULT_SIG_RESTART SIGUSR1

View file

@ -161,7 +161,8 @@ int __pthread_manager(void *arg)
break;
case REQ_DEBUG:
/* Make gdb aware of new thread */
if (__pthread_threads_debug) raise(__pthread_sig_cancel);
if (__pthread_threads_debug && __pthread_sig_debug > 0)
raise(__pthread_sig_debug);
restart(request.req_thread);
break;
}
@ -554,7 +555,7 @@ static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode)
_exit(0);
}
/* Handler for __pthread_sig_restart in thread manager thread */
/* Handler for __pthread_sig_cancel in thread manager thread */
void __pthread_manager_sighandler(int sig)
{

View file

@ -150,9 +150,11 @@ const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct,
#ifdef SIGRTMIN
int __pthread_sig_restart;
int __pthread_sig_cancel;
int __pthread_sig_debug;
#else
int __pthread_sig_restart = DEFAULT_SIG_RESTART;
int __pthread_sig_cancel = DEFAULT_SIG_CANCEL;
int __pthread_sig_debug = 0; /* disabled */
#endif
/* These variables are used by the setup code. */
@ -169,6 +171,7 @@ static void pthread_handle_sigrestart(int sig);
static void pthread_handle_sigcancel(int sig, struct sigcontext ctx);
static void pthread_handle_sigrestart(int sig, struct sigcontext ctx);
#endif
static void pthread_handle_sigdebug(int sig);
/* Initialize the pthread library.
Initialization is split in two functions:
@ -220,12 +223,17 @@ static void pthread_initialize(void)
/* Allocate the signals used. */
__pthread_sig_restart = __libc_allocate_rtsig (1);
__pthread_sig_cancel = __libc_allocate_rtsig (1);
if (__pthread_sig_restart < 0 || __pthread_sig_cancel < 0)
__pthread_sig_debug = __libc_allocate_rtsig (2);
if (__pthread_sig_restart < 0 ||
__pthread_sig_cancel < 0 ||
__pthread_sig_debug < 0)
{
/* The kernel does not support real-time signals. Use as before
the available signals in the fixed set. */
the available signals in the fixed set.
Debugging is not supported in this case. */
__pthread_sig_restart = DEFAULT_SIG_RESTART;
__pthread_sig_cancel = DEFAULT_SIG_CANCEL;
__pthread_sig_debug = 0;
}
#endif
/* Setup signal handlers for the initial thread.
@ -237,8 +245,7 @@ static void pthread_initialize(void)
sa.sa_handler = (__sighandler_t) pthread_handle_sigrestart;
#endif
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART; /* does not matter for regular threads, but
better for the thread manager */
sa.sa_flags = 0;
__sigaction(__pthread_sig_restart, &sa, NULL);
#ifndef __i386__
sa.sa_handler = pthread_handle_sigcancel;
@ -247,7 +254,12 @@ static void pthread_initialize(void)
#endif
sa.sa_flags = 0;
__sigaction(__pthread_sig_cancel, &sa, NULL);
if (__pthread_sig_debug > 0) {
sa.sa_handler = pthread_handle_sigdebug;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
__sigaction(__pthread_sig_debug, &sa, NULL);
}
/* Initially, block __pthread_sig_restart. Will be unblocked on demand. */
sigemptyset(&mask);
sigaddset(&mask, __pthread_sig_restart);
@ -479,16 +491,8 @@ static void pthread_handle_sigrestart(int sig, struct sigcontext ctx)
/* The handler for the CANCEL signal checks for cancellation
(in asynchronous mode), for process-wide exit and exec requests.
For the thread manager thread, redirect the signal to
__pthread_manager_sighandler.
The debugging strategy is as follows:
On reception of a REQ_DEBUG request (sent by new threads created to
the thread manager under debugging mode), the thread manager throws
__pthread_sig_cancel to itself. The debugger (if active) intercepts
this signal, takes into account new threads and continue execution
of the thread manager by propagating the signal because it doesn't
know what it is specifically done for. In the current implementation,
the thread manager simply discards it. */
For the thread manager thread, redirect the signal to
__pthread_manager_sighandler. */
#ifndef __i386__
static void pthread_handle_sigcancel(int sig)
@ -528,6 +532,21 @@ static void pthread_handle_sigcancel(int sig, struct sigcontext ctx)
}
}
/* Handler for the DEBUG signal.
The debugging strategy is as follows:
On reception of a REQ_DEBUG request (sent by new threads created to
the thread manager under debugging mode), the thread manager throws
__pthread_sig_cancel to itself. The debugger (if active) intercepts
this signal, takes into account new threads and continue execution
of the thread manager by propagating the signal because it doesn't
know what it is specifically done for. In the current implementation,
the thread manager simply discards it. */
static void pthread_handle_sigdebug(int sig)
{
/* Nothing */
}
/* Reset the state of the thread machinery after a fork().
Close the pipe used for requests and set the main thread to the forked
thread.

View file

@ -91,19 +91,23 @@ static void pthread_sighandler(int signo)
THREAD_SETMEM(self, p_in_sighandler, NULL);
}
/* The wrapper around sigaction. Install our own signal handler
around the signal. */
int sigaction(int sig, const struct sigaction * act,
struct sigaction * oact)
{
struct sigaction newact;
struct sigaction *newactp;
if (sig == __pthread_sig_restart || sig == __pthread_sig_cancel)
if (sig == __pthread_sig_restart ||
sig == __pthread_sig_cancel ||
(sig == __pthread_sig_debug && __pthread_sig_debug > 0))
return EINVAL;
if (act)
{
newact = *act;
if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL
&& sig < NSIG)
&& sig > 0 && sig < NSIG)
newact.sa_handler = pthread_sighandler;
newactp = &newact;
}
@ -111,7 +115,7 @@ int sigaction(int sig, const struct sigaction * act,
newactp = NULL;
if (__sigaction(sig, newactp, oact) == -1)
return -1;
if (sig < NSIG)
if (sig > 0 && sig < NSIG)
{
if (oact != NULL)
oact->sa_handler = sighandler[sig];
@ -121,20 +125,41 @@ int sigaction(int sig, const struct sigaction * act,
return 0;
}
/* A signal handler that does nothing */
static void pthread_null_sighandler(int sig) { }
/* sigwait -- synchronously wait for a signal */
int sigwait(const sigset_t * set, int * sig)
{
volatile pthread_descr self = thread_self();
sigset_t mask;
int s;
sigjmp_buf jmpbuf;
struct sigaction sa;
/* Get ready to block all signals except those in set
and the cancellation signal */
and the cancellation signal.
Also check that handlers are installed on all signals in set,
and if not, install our dummy handler. This is conformant to
POSIX: "The effect of sigwait() on the signal actions for the
signals in set is unspecified." */
sigfillset(&mask);
sigdelset(&mask, __pthread_sig_cancel);
for (s = 1; s <= NSIG; s++) {
if (sigismember(set, s) && s != __pthread_sig_cancel)
if (sigismember(set, s) &&
s != __pthread_sig_restart &&
s != __pthread_sig_cancel &&
s != __pthread_sig_debug) {
sigdelset(&mask, s);
if (sighandler[s] == NULL ||
sighandler[s] == SIG_DFL ||
sighandler[s] == SIG_IGN) {
sa.sa_handler = pthread_null_sighandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(s, &sa, NULL);
}
}
}
/* Test for cancellation */
if (sigsetjmp(jmpbuf, 1) == 0) {
@ -157,6 +182,8 @@ int sigwait(const sigset_t * set, int * sig)
return 0;
}
/* Redefine raise() to send signal to calling thread only,
as per POSIX 1003.1c */
int raise (int sig)
{
int retcode = pthread_kill(pthread_self(), sig);