commit 7813035

Michael Forney  ·  2018-11-14 07:48:18 +0000 UTC
parent 4ab2053
launch: Use self-pipe to handle signals

It is not safe to call these ioctls in signal handlers.
1 files changed,  +38, -34
+38, -34
  1@@ -73,6 +73,7 @@ static struct {
  2 } original_vt_state;
  3 
  4 static bool nflag;
  5+static int sigfd[2];
  6 
  7 static void __attribute__((noreturn, format(printf, 1, 2)))
  8 die(const char *format, ...);
  9@@ -173,29 +174,9 @@ deactivate(void)
 10 }
 11 
 12 static void
 13-handle_chld(int signal)
 14+handle_signal(int sig)
 15 {
 16-	int status;
 17-
 18-	if (!child_pid)
 19-		return;
 20-	wait(&status);
 21-	cleanup();
 22-	exit(WEXITSTATUS(status));
 23-}
 24-
 25-static void
 26-handle_usr1(int signal)
 27-{
 28-	deactivate();
 29-	ioctl(launcher.tty_fd, VT_RELDISP, 1);
 30-}
 31-
 32-static void
 33-handle_usr2(int signal)
 34-{
 35-	ioctl(launcher.tty_fd, VT_RELDISP, VT_ACKACQ);
 36-	activate();
 37+	write(sigfd[1], (char[]){sig}, 1);
 38 }
 39 
 40 static void
 41@@ -403,15 +384,41 @@ error0:
 42 
 43 static void
 44 run(int fd) {
 45-	struct pollfd pollfd = { .fd = fd, .events = POLLIN };
 46+	struct pollfd fds[] = {
 47+		{.fd = fd, .events = POLLIN},
 48+		{.fd = sigfd[0], .events = POLLIN},
 49+	};
 50+	int status;
 51+	char sig;
 52 
 53 	for (;;) {
 54-		if (poll(&pollfd, 1, -1) < 0) {
 55+		if (poll(fds, ARRAY_LENGTH(fds), -1) < 0) {
 56 			if (errno == EINTR)
 57 				continue;
 58 			die("poll:");
 59 		}
 60-		handle_socket_data(pollfd.fd);
 61+		if (fds[0].revents)
 62+			handle_socket_data(fd);
 63+		if (fds[1].revents) {
 64+			if (read(sigfd[0], &sig, 1) <= 0)
 65+				continue;
 66+			switch (sig) {
 67+			case SIGCHLD:
 68+				if (!child_pid)
 69+					break;
 70+				wait(&status);
 71+				cleanup();
 72+				exit(WEXITSTATUS(status));
 73+			case SIGUSR1:
 74+				deactivate();
 75+				ioctl(launcher.tty_fd, VT_RELDISP, 1);
 76+				break;
 77+			case SIGUSR2:
 78+				ioctl(launcher.tty_fd, VT_RELDISP, VT_ACKACQ);
 79+				activate();
 80+				break;
 81+			}
 82+		}
 83 	}
 84 }
 85 
 86@@ -421,7 +428,7 @@ main(int argc, char *argv[])
 87 	int option;
 88 	int sock[2];
 89 	char *vt = NULL, buf[64];
 90-	struct sigaction action = { 0 };
 91+	struct sigaction action = {.sa_handler = handle_signal};
 92 	sigset_t set;
 93 	posix_spawnattr_t attr;
 94 
 95@@ -449,17 +456,14 @@ main(int argc, char *argv[])
 96 	if (fcntl(sock[0], F_SETFD, FD_CLOEXEC) == -1)
 97 		die("failed set CLOEXEC on socket:");
 98 
 99-	action.sa_handler = &handle_chld;
100+	if (pipe2(sigfd, O_CLOEXEC) == -1)
101+		die("pipe:");
102 	if (sigaction(SIGCHLD, &action, NULL) == -1)
103-		die("failed to register signal handler for SIGCHLD:");
104-
105-	action.sa_handler = &handle_usr1;
106+		die("sigaction SIGCHLD:");
107 	if (sigaction(SIGUSR1, &action, NULL) == -1)
108-		die("failed to register signal handler for SIGUSR1:");
109-
110-	action.sa_handler = &handle_usr2;
111+		die("sigaction SIGUSR1:");
112 	if (sigaction(SIGUSR2, &action, NULL) == -1)
113-		die("failed to register signal handler for SIGUSR2:");
114+		die("sigaction SIGUSR2:");
115 
116 	sigfillset(&set);
117 	sigdelset(&set, SIGCHLD);