Date: Fri, 11 Jun 2004 01:55:14 -0700 From: Sean McNeil <sean@mcneil.com> To: Daniel Eischen <eischen@vigrid.com> Cc: freebsd-amd64@freebsd.org Subject: Re: signal handler priority issue Message-ID: <1086944114.76446.5.camel@server.mcneil.com> In-Reply-To: <Pine.GSO.4.10.10406110432370.12394-100000@pcnet5.pcnet.com> References: <Pine.GSO.4.10.10406110432370.12394-100000@pcnet5.pcnet.com>
next in thread | previous in thread | raw e-mail | index | archive | help
(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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1086944114.76446.5.camel>