Date: Wed, 31 Oct 2001 12:29:00 GMT From: Nicholas Barnes <nb@ravenbrook.com> To: FreeBSD-gnats-submit@freebsd.org Cc: mps-staff@ravenbrook.com Subject: bin/31661: pthread_kill signal handler doesn't get sigcontext or ucontext Message-ID: <200110311229.f9VCT0Q23978@thrush.ravenbrook.com>
next in thread | raw e-mail | index | archive | help
>Number: 31661
>Category: bin
>Synopsis: pthread_kill signal handler doesn't get sigcontext or ucontext
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Oct 31 04:30:06 PST 2001
>Closed-Date:
>Last-Modified:
>Originator: Nicholas Barnes
>Release: FreeBSD 4.4-STABLE i386
>Organization:
Ravenbrook Limited
>Environment:
System: FreeBSD thrush.ravenbrook.com 4.4-STABLE FreeBSD 4.4-STABLE #2: Mon Oct 15 10:12:14 BST 2001 nb@thrush.ravenbrook.com:/usr/obj/usr/src/sys/THRUSH-2001-04-17 i386
cvsup/buildworld/installworld on 2001-10-15.
>Description:
The signal handler for a signal caused by pthread_kill only receives a
single useful argument: the signal. Man sigaction says it should get
either code + sigcontext or info + ucontext (depending on whether
SA_SIGINFO is set). But in fact these subsequent arguments always get
0 (or NULL).
This means that I can't use pthread_kill to suspend a thread and get
its context; required for some kinds of garbage collection.
>How-To-Repeat:
/* Test program to show that per-thread signals are not delivered with
* useful code, sigcontext, siginfo, or ucontext.
* FreeBSD 4.4-STABLE, 2001-10-31.
* Nick Barnes, 2001-10-31.
*/
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
/* variables to record the arguments passed to signal handlers */
static int ANSIHandled = 0;
static int ANSISignal = 0;
static pthread_t ANSIPthread = NULL;
static int BSDHandled = 0;
static int BSDSignal = 0;
static int BSDCode = 0;
static struct sigcontext *BSDSigcontext = NULL;
static pthread_t BSDPthread = NULL;
static int PosixHandled = 0;
static int PosixSignal = 0;
static siginfo_t *PosixInfo = NULL;
static void *PosixContext = NULL;
static pthread_t PosixPthread = NULL;
/* a mutex for all the threads to wait on */
static pthread_mutex_t mutex;
/* three possible signal handlers. See man sigaction. */
/* ANSI signal handler prototype */
static void ANSIHandler(int sig)
{
ANSIHandled = 1;
ANSISignal = sig;
ANSIPthread = pthread_self();
}
/* BSD signal handler prototype */
static void BSDHandler(int sig, int code, struct sigcontext *scp)
{
BSDHandled = 1;
BSDSignal = sig;
BSDCode = code;
BSDSigcontext = scp;
BSDPthread = pthread_self();
}
/* Posix signal handler prototype */
static void PosixHandler(int sig, siginfo_t *info, void *context)
{
PosixHandled = 1;
PosixSignal = sig;
PosixInfo = info;
PosixContext = context;
PosixPthread = pthread_self();
}
/* A function for a thread to run. */
void *ThreadStart(void *arg)
{
const char *name = (const char *)arg;
pthread_t self = pthread_self();
printf("%s is alive: 0x%08x\n", name, self);
/* try to lock the mutex. This will sleep for ever */
pthread_mutex_lock(&mutex);
}
#define ANSISIG SIGUSR1
#define BSDSIG SIGUSR2
#define PosixSIG SIGXFSZ
int main(void)
{
struct sigaction ANSISigaction, BSDSigaction, PosixSigaction;
pthread_t ANSIThread, BSDThread, PosixThread;
ANSISigaction.sa_handler = ANSIHandler;
ANSISigaction.sa_flags = 0;
sigaction(ANSISIG, &ANSISigaction, NULL);
BSDSigaction.sa_handler = BSDHandler;
BSDSigaction.sa_flags = 0;
sigaction(BSDSIG, &BSDSigaction, NULL);
PosixSigaction.sa_sigaction = PosixHandler;
PosixSigaction.sa_flags = SA_SIGINFO;
sigaction(PosixSIG, &PosixSigaction, NULL);
pthread_mutex_init(&mutex, NULL);
pthread_mutex_lock(&mutex);
pthread_create(&ANSIThread, NULL, ThreadStart, "ANSI");
pthread_create(&BSDThread, NULL, ThreadStart, "BSD");
pthread_create(&PosixThread, NULL, ThreadStart, "Posix");
printf("ANSI Thread 0x%08x\n", ANSIThread);
printf("BSD Thread 0x%08x\n", BSDThread);
printf("Posix Thread 0x%08x\n", PosixThread);
/* wait for the threads to be alive */
printf("waiting for the threads to be alive\n");
/* I know I could use a pthreads mechanism for this,
* but I wanted to keep it simple. */
sleep(5);
pthread_kill(ANSIThread, ANSISIG);
pthread_kill(BSDThread, BSDSIG);
pthread_kill(PosixThread, PosixSIG);
/* wait for the signals to be delivered. */
printf("waiting for the signals to be delivered\n");
/* I know I could use a pthreads mechanism for this,
* but I wanted to keep it simple. */
sleep(5);
printf("ANSI: Handled %d signal %d pthread 0x%08x\n",
ANSIHandled, ANSISignal, ANSIPthread);
printf("BSD: Handled %d signal %d pthread 0x%08x code %d sigcontext 0x%08x\n",
BSDHandled, BSDSignal, BSDPthread, BSDCode, BSDSigcontext);
printf("Posix: Handled %d signal %d pthread 0x%08x info 0x%08x context 0x%08x\n",
PosixHandled, PosixSignal, PosixPthread, PosixInfo, PosixContext);
return 0;
}
>Fix:
Not known. May be related to the fact that _thread_sig_send()
(lib/libc_r/uthread/uthread_sig.c) passes 0 as the has_args argument
to thread_sig_add(), under certain circumstances.
>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?200110311229.f9VCT0Q23978>
