From dac8e8449dd134f9c43378e9ad1993ebc86080da Mon Sep 17 00:00:00 2001 From: Martin Lucina Date: Sat, 30 Jan 2010 17:39:42 +0100 Subject: Implement synchronous signal handling This is to demonstrate how SIGINT, etc. can be handled properly even if the application thread is blocked on zmq_recv(). --- zmq-camera.c | 73 ++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/zmq-camera.c b/zmq-camera.c index 717eade..fb46899 100644 --- a/zmq-camera.c +++ b/zmq-camera.c @@ -64,16 +64,9 @@ void *sender_thread (void *arg) unicap_data_buffer_t src_buffer; unicap_data_buffer_t dest_buffer; unicap_data_buffer_t *returned_buffer; - sigset_t block_set; sender_args = (struct sender_args_t *)arg; - /* Block SIGALRM in the sender thread since it's used for timers in the - main thread */ - sigemptyset (&block_set); - sigaddset (&block_set, SIGALRM); - pthread_sigmask (SIG_BLOCK, &block_set, NULL); - /* Create a ZMQ_PUB socket for sending video data and connect it to both an inproc endpoint for the local loopback view and bind to the endpoint specified by the user. */ @@ -218,9 +211,47 @@ void *sender_thread (void *arg) } /* - * Print usage and exit. + * Signal handling thread + */ + +/* Global variable used to signal if an alarm has expired */ +volatile int alarm_expired = 0; + +void *signal_thread (void *arg) +{ + sigset_t wait_set; + int rc, signo; + + sigemptyset (&wait_set); + sigaddset (&wait_set, SIGTERM); + sigaddset (&wait_set, SIGINT); + sigaddset (&wait_set, SIGQUIT); + sigaddset (&wait_set, SIGALRM); + + while (1) { + rc = sigwait (&wait_set, &signo); + assert (rc == 0); + + switch (signo) { + case SIGTERM: + case SIGINT: + case SIGQUIT: + fprintf (stderr, "Exiting.\n"); + exit (1); + case SIGALRM: + alarm_expired = 1; + break; + default: + ; /* Ignored */ + } + } +} + +/* + * Main thread */ +/* Print usage and exit. */ void err_usage(char *error) { const char usage[] = \ @@ -247,17 +278,7 @@ void err_usage(char *error) exit (1); } -/* - * Main thread - */ - -volatile int alarm_expired = 0; - -void alarm_handler (int signo) -{ - alarm_expired = 1; -} - +/* Main program. */ int main (int argc, char *argv []) { void *ctx, *s; @@ -269,7 +290,7 @@ int main (int argc, char *argv []) uint32_t image_width, image_height; int sdl_initialised = 0; int quit = 0; - struct sigaction alarm_action; + sigset_t block_set; struct itimerval alarm_timer; uint64_t received_fps = 0; uint64_t received_bps = 0; @@ -304,6 +325,14 @@ int main (int argc, char *argv []) err_usage ("Please specify either the -r or -s option"); endpoint = argv [optind]; + /* Block signal handling in all application and 0MQ threads and + start a separate thread to handle all signals synchronously */ + sigfillset (&block_set); + pthread_sigmask (SIG_SETMASK, &block_set, NULL); + pthread_t signal; + rc = pthread_create (&signal, NULL, signal_thread, NULL); + assert (rc == 0); + /* Initialise 0MQ infrastructure for 2 application threads and a single I/O thread */ ctx = zmq_init (2, 1, 0); @@ -345,10 +374,6 @@ int main (int argc, char *argv []) /* Set up an interval timer to fire SIGALRM once a second so that we can update bandwidth and fps statistics */ - alarm_action.sa_flags = 0; - alarm_action.sa_handler = alarm_handler; - rc = sigaction (SIGALRM, &alarm_action, NULL); - assert (rc == 0); alarm_timer.it_interval.tv_sec = 1; alarm_timer.it_interval.tv_usec = 0; alarm_timer.it_value.tv_sec = 1; -- cgit v1.2.3