| Summary: | pthread_kill signal handler doesn't get sigcontext or ucontext | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Nicholas Barnes <nb> |
| Component: | bin | Assignee: | freebsd-threads (Nobody) <threads> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | CC: | mps-staff |
| Priority: | Normal | ||
| Version: | 4.4-STABLE | ||
| Hardware: | Any | ||
| OS: | Any | ||
I forgot to provide the results of running the test program. Here they are. The bug is demonstrated by the last two lines of output: the code, sigcontext, info, and context variables are all zero. $ cc -pthread test.c test.c: In function `main': test.c:87: warning: assignment from incompatible pointer type $ ./a.out ANSI Thread 0x0804c400 BSD Thread 0x0804cc00 Posix Thread 0x0805f000 waiting for the threads to be alive ANSI is alive: 0x0804c400 BSD is alive: 0x0804cc00 Posix is alive: 0x0805f000 waiting for the signals to be delivered ANSI: Handled 1 signal 30 pthread 0x0804c400 BSD: Handled 1 signal 31 pthread 0x0804cc00 code 0 sigcontext 0x00000000 Posix: Handled 1 signal 25 pthread 0x0805f000 info 0x00000000 context 0x00000000 $ Responsible Changed From-To: freebsd-bugs->jasone I'll take a look at this. Responsible Changed From-To: jasone->freebsd-bugs Responsible Changed From-To: freebsd-bugs->freebsd-threads Assign to threads mailing list Hi, I just tried your test program on FreeBSD-CURRENT. When linked with -lc_r, the output is: NSI Thread 0x0804c400 BSD Thread 0x0804cc00 Posix Thread 0x0805f000 waiting for the threads to be alive ANSI is alive: 0x0804c400 BSD is alive: 0x0804cc00 Posix is alive: 0x0805f000 waiting for the signals to be delivered ANSI: Handled 1 signal 30 pthread 0x0804c400 BSD: Handled 1 signal 31 pthread 0x0804cc00 code 0 sigcontext 0x00000000 Posix: Handled 1 signal 25 pthread 0x0805f000 info 0x00000000 context 0x00000000 When linked with -lpthread, the output is: ANSI Thread 0x08053400 BSD Thread 0x08053600 Posix Thread 0x08053800 waiting for the threads to be alive ANSI is alive: 0x08053400 BSD is alive: 0x08053600 Posix is alive: 0x08053800 waiting for the signals to be delivered ANSI: Handled 1 signal 30 pthread 0x08053400 BSD: Handled 1 signal 31 pthread 0x08053600 code 0 sigcontext 0xbfaddbe8 Posix: Handled 1 signal 25 pthread 0x08053800 info 0xbfacdb58 context 0xbfacdbe8 You mentioned that the bug is demonstrated by the fact that sigcontext and context are 0 in the last two lines of the output. This problem does not seem to exist for the new pthread library. -- Craig Rodrigues rodrigc@crodrigues.org At 2004-02-02 21:39:30+0000, Craig Rodrigues writes:
> This problem does not seem to exist for the new pthread library.
Great, thanks! I must try out -CURRENT.
The underlying functionality is essential for some applications
(basically anything which needs to pause other threads in order to
introspect on their stacks, e.g. for garbage collection).
Nick B
State Changed From-To: open->closed This is written against libc_r's implementation of pthread_kill; libpthread does provide full signal handler arguments to pthread_kill. Still it iw worth noting that trying to do anything sane with a context from a pthread_kill() is probably not what you want especially for scope process threads. pthread_kill() is a simulated interrupt and the threads interrupted context is generated by the threads library -- it is not like a real signal interrupted the thread while it was running. |
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. 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. 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; }