blob: 40634122c24b732a00fb984537cba46289471d2f [file] [log] [blame]
/********************************************************
* An example source module to accompany...
*
* "Using POSIX Threads: Programming with Pthreads"
* by Brad nichols, Dick Buttlar, Jackie Farrell
* O'Reilly & Associates, Inc.
*
********************************************************
* sig.c
*
* Simple example of pthreads and signals.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <pthread.h>
#define MAX_NUM_THREADS 10
void *catch_usr1(void *p)
{
int signo=SIGUSR1;
/* struct sigaction action; */
int caught;
sigset_t sigs_to_catch;
/* Identify our thread */
printf("\ncatchit() signal %d processing running as thread 0x%x \n",
signo, (int)pthread_self());
printf("Someone please send pid %d a SIGUSR1\n", getpid());
/*
* We inherited a thread sigmask with all the signals
* blocked. So, we can wait on whatever signals we're
* interested in and (as long as no other thread waits
* for them) we'll be sure return from sigwait() to
* handle it.
*/
/* set this thread's signal mask to block out all other signals */
sigemptyset(&sigs_to_catch);
sigaddset(&sigs_to_catch, signo);
sigwait(&sigs_to_catch, &caught);
printf("\ncatchit() signal %d processing thread caught signal %d\n",
signo, caught);
return(NULL);
}
void bugcatcher(int sig)
{
printf("The BUGCATCHER caught signal %d in thread 0x%x\n",
sig, (int)pthread_self());
pthread_exit(0);
}
void *cause_sig_sync(void *p)
{
int i, id;
sigset_t sigs_to_catch;
/* Identify our thread */
printf("cause_sig_sync() running in thread 0x%x\n", (int)pthread_self());
/* set this thread's signal mask to block out all other signals */
sigemptyset(&sigs_to_catch);
sigaddset(&sigs_to_catch, SIGSEGV);
sigaddset(&sigs_to_catch, SIGBUS);
pthread_sigmask(SIG_UNBLOCK, &sigs_to_catch, NULL);
/* Loop simulating useful processing in this thread */
for(i=1;i==i;i++) {
printf("printing count: %4d\r",i);
if (i%100 == 0) {
id = *(int *)p; /* Guaranteed bad address */
}
}
return(NULL);
}
extern int
main(void)
{
int i;
pthread_t threads[MAX_NUM_THREADS];
int num_threads = 0;
sigset_t sigs_to_block;
struct sigaction action;
/* Identify our thread */
printf("main() running in thread 0x%x\n", (int)pthread_self());
/*
* Set this thread's signal mask to block out all other signals
* Other threads will inherit the mask
*/
sigfillset(&sigs_to_block);
pthread_sigmask(SIG_BLOCK, &sigs_to_block, NULL);
/* Set signal handler for catching SIGSEGV and SIGBUS */
action.sa_handler=bugcatcher;
sigaction(SIGSEGV, &action, NULL);
sigaction(SIGBUS, &action, NULL);
/* spawn the threads */
/* Make sure we can catch synchronous signals as exceptions */
pthread_create(&threads[num_threads++],
NULL,
cause_sig_sync,
NULL);
/* Rather than install the action/handler for the process,
we create a thread to wait for the signal */
pthread_create(&threads[num_threads++],
NULL,
catch_usr1,
NULL);
printf("main()\t\t\t\t%d threads created\n",num_threads);
/* wait until all threads have finished */
for (i = 0; i < num_threads; i++) {
pthread_join(threads[i], NULL);
printf("main()\t\tjoined to thread %d \n", i);
}
printf("main()\t\tall %d threads have finished. \n", num_threads);
return 0;
}