summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Lucina <mato@kotelna.sk>2010-01-30 17:39:42 +0100
committerMartin Lucina <mato@kotelna.sk>2010-01-30 17:39:42 +0100
commitdac8e8449dd134f9c43378e9ad1993ebc86080da (patch)
tree0cb82ae8ba5cbddc709469b65762bff71c8e39b4
parentb8beebbef45b5f99b53256d6c0cc30c1785f8a90 (diff)
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().
-rw-r--r--zmq-camera.c73
1 files 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;