signal handler priority issue
Sean McNeil
sean at mcneil.com
Fri Jun 11 09:28:59 GMT 2004
Sorry for top-posting, but it may be easier to read this way....
The program below has an optimization bug in that done isn't declare
volatile. With that fixed, it works just fine. I've been attempting to
get boehm-gc working and it seems OK with libc_r, but fails with
libpthread. It is essentially doing what the program below does, but
for some reason it gets stuck. Has anyone else been experimenting with
boehm-gc?
Also, it would really help if I had a debugger that worked with kse
threads. How is that going? Tracking down pthread issues right now has
been difficult with the current debugger. Can anyone throw some patches
my way that may help?
On Fri, 2004-06-11 at 01:55, Sean McNeil wrote:
> (I've cc'd the amd64 list so here is some background)
>
> I'm experiencing some odd behavior with signals and threads. Daniel has
> managed to isolate it to an example program that works. Except....
>
> OK, so maybe this is an optimization bug. The following works fine with
> no optimization, but with -O or -O2 it fails on an amd64. Can someone
> test with various optimizations on i386?
>
> Compiled with
>
> cc -o test_sr test_sr.c -pthread
> works
>
> cc -O -o test_sr test_sr.c -pthread
> or
> cc -O2 -o test_sr test_sr.c -pthread
> hangs
>
> /*
> * test_sr.c
> *
> * Demonstrate use of signals & semaphores for suspending and
> * resuming threads.
> */
> #include <errno.h>
> #include <pthread.h>
> #include <semaphore.h>
> #include <signal.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <ucontext.h>
> #include <unistd.h>
>
> #ifndef NUM_THREADS
> #define NUM_THREADS 5
> #endif
>
> static sem_t semaphore;
> static int done = 0;
> static pthread_t tids[NUM_THREADS];
>
> static void
> errno_abort(char *msg)
> {
> printf("%s, errno %d\n", msg, errno);
> abort();
> }
>
> static void
> err_abort(int status, char *msg)
> {
> printf("%s, status %d\n", msg, status);
> abort();
> }
>
> static void
> sighandler1(int sig, siginfo_t *info, ucontext_t *ucp)
> {
> sigset_t mask;
> int i;
> pthread_t self = pthread_self();
>
> for (i=0; i<NUM_THREADS && self != tids[i]; i++);
>
> printf("Thread %d pausing.\n", i);
> sem_post(&semaphore);
>
> sigfillset(&mask);
> sigdelset(&mask, SIGUSR2);
> sigsuspend(&mask);
> printf("Thread %d successfully resumed.\n", i);
> }
>
> static void
> sighandler2(int sig, siginfo_t *info, ucontext_t *ucp)
> {
> int i;
> pthread_t self = pthread_self();
>
> for (i=0; i<NUM_THREADS && self != tids[i]; i++);
>
> printf("Thread %d got resume signal.\n", i);
> }
>
> /*
> * Thread start routine to wait on a semaphore.
> */
> static void *
> worker(void *arg)
> {
> int num = (int)arg;
> int x;
>
> num = (int)arg;
> x = num * 10;
>
> printf ("Thread %d starting.\n", num);
> while (!done) {
> x = x + 1;
> x = x - 1;
> }
> printf("Thread %d stopping.\n", num);
>
> return (NULL);
> }
>
> static void
> pause_threads(void)
> {
> int i;
>
> printf("Master: pausing all threads.\n");
> for (i = 0; i < NUM_THREADS; i++) {
> pthread_kill(tids[i], SIGUSR1);
> }
> for (i = 0; i < NUM_THREADS; i++) {
> if (sem_wait(&semaphore) == -1)
> errno_abort("Wait on semaphore");
> }
> }
>
> static void
> resume_threads(void)
> {
> int i;
>
> printf("Master: resuming all threads.\n");
> for (i = 0; i < NUM_THREADS; i++) {
> pthread_kill(tids[i], SIGUSR2);
> }
> }
>
> static void *
> pause_resume(void *arg)
> {
> int i;
>
> for (i = 0; i < 5; i++) {
> pause_threads();
> resume_threads();
> }
>
> return NULL;
> }
>
> int
> main(int argc, char *argv[])
> {
> pthread_t prid;
> struct sigaction act;
> int status;
> int i;
>
> if (sem_init (&semaphore, 0, 0) == -1)
> errno_abort ("Init semaphore");
>
> /* Mask all signals while in the signal handler. */
> sigfillset(&act.sa_mask);
> act.sa_flags = SA_RESTART;
>
> act.sa_handler = sighandler1;
> sigaction(SIGUSR1, &act, NULL);
>
> act.sa_handler = sighandler2;
> sigaction(SIGUSR2, &act, NULL);
>
> /*
> * Create some worker threads.
> */
> for (i = 0; i < NUM_THREADS; i++) {
> status = pthread_create(&tids[i], NULL, worker, (void
> *)i);
> if (status != 0)
> err_abort (status, "Create thread");
> }
>
> pthread_create (&prid, NULL, pause_resume, NULL);
> pthread_join(prid, NULL);
>
> for (i = 0; i < 5; i++) {
> pause_threads();
> resume_threads();
> }
>
> done = 1;
>
> /*
> * Wait for all threads to complete.
> */
> for (i = 0; i < NUM_THREADS; i++) {
> status = pthread_join(tids[i], NULL);
> if (status != 0)
> err_abort(status, "Join thread");
> }
> return (0);
> }
>
More information about the freebsd-amd64
mailing list