In a mode of 'monitor, event loop runs to dispatch asynchronous event emitted by control node. In this case, installation of signal handler is good for safe cancellation.
This commit install signal handler to allow some operation to clear event loop.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- alsactl/monitor.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/alsactl/monitor.c b/alsactl/monitor.c index 8351a79..a2abacb 100644 --- a/alsactl/monitor.c +++ b/alsactl/monitor.c @@ -20,8 +20,14 @@ #include "aconfig.h" #include "version.h" #include <stdio.h> +#include <stdbool.h> +#include <string.h> +#include <signal.h> #include <alsa/asoundlib.h>
+static int signal_type; +static bool interrupted; + static int open_ctl(const char *name, snd_ctl_t **ctlp) { snd_ctl_t *ctl; @@ -84,6 +90,30 @@ static int print_event(int card, snd_ctl_t *ctl) return 0; }
+static void handle_unix_signal_for_finish(int sig) +{ + signal_type = sig; + interrupted = true; +} + +static int prepare_signal_handler(void) +{ + struct sigaction sa = {0}; + + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = handle_unix_signal_for_finish; + + if (sigaction(SIGABRT, &sa, NULL) < 0) + return -errno; + if (sigaction(SIGINT, &sa, NULL) < 0) + return -errno; + if (sigaction(SIGTERM, &sa, NULL) < 0) + return -errno; + + return 0; +} + #define MAX_CARDS 256
int monitor(const char *name) @@ -93,6 +123,10 @@ int monitor(const char *name) int show_cards; int i, err = 0;
+ err = prepare_signal_handler(); + if (err < 0) + return err; + if (!name) { int card = -1; while (snd_card_next(&card) >= 0 && card >= 0) { @@ -117,14 +151,26 @@ int monitor(const char *name) show_cards = 0; }
+ interrupted = false; for (;ncards > 0;) { struct pollfd fds[ncards];
+ if (interrupted) { + printf("interrupted: %s\n", strsignal(signal_type)); + break; + } + for (i = 0; i < ncards; i++) snd_ctl_poll_descriptors(ctls[i], &fds[i], 1);
err = poll(fds, ncards, -1); if (err <= 0) { + // Catch this case by an above condition statement to + // check value set by signal handler. I note that + // poll(2) returns EINTR even if configured with + // SA_RESTART. + if (errno == EINTR) + continue; err = 0; break; }