[alsa-devel] [PATCH][RFC][alsa-utils 1/9] alsactl: install signal handler

Takashi Sakamoto o-takashi at sakamocchi.jp
Fri Oct 5 16:47:21 CEST 2018


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 at 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;
 		}
-- 
2.19.0



More information about the Alsa-devel mailing list