commit d82a721

Michael Forney  ·  2016-04-30 09:55:56 +0000 UTC
parent ce2565f
launch: Use posix_spawn
1 files changed,  +45, -62
+45, -62
  1@@ -1,6 +1,6 @@
  2 /* swc: launch/launch.c
  3  *
  4- * Copyright (c) 2013, 2014 Michael Forney
  5+ * Copyright (c) 2013, 2014, 2016 Michael Forney
  6  *
  7  * Based in part upon weston-launch.c from weston which is:
  8  *
  9@@ -31,6 +31,7 @@
 10 #include <stdio.h>
 11 #include <stdbool.h>
 12 #include <string.h>
 13+#include <spawn.h>
 14 #include <unistd.h>
 15 #include <errno.h>
 16 #include <fcntl.h>
 17@@ -405,14 +406,29 @@ error0:
 18 	exit(EXIT_FAILURE);
 19 }
 20 
 21+static void
 22+run(int fd) {
 23+	struct pollfd pollfd = { .fd = fd, .events = POLLIN };
 24+
 25+	for (;;) {
 26+		if (poll(&pollfd, 1, -1) < 0) {
 27+			if (errno == EINTR)
 28+				continue;
 29+			die("poll:");
 30+		}
 31+		handle_socket_data(pollfd.fd);
 32+	}
 33+}
 34+
 35 int
 36 main(int argc, char *argv[])
 37 {
 38 	int option;
 39-	int sockets[2];
 40-	char *vt = NULL, vt_buf[64];
 41+	int sock[2];
 42+	char *vt = NULL, buf[64];
 43 	struct sigaction action = { 0 };
 44 	sigset_t set;
 45+	posix_spawnattr_t attr;
 46 
 47 	while ((option = getopt(argc, argv, "ns:t:")) != -1) {
 48 		switch (option) {
 49@@ -433,12 +449,12 @@ main(int argc, char *argv[])
 50 	if (argc - optind < 1)
 51 		usage(argv[0]);
 52 
 53-	if (socketpair(AF_LOCAL, SOCK_SEQPACKET, 0, sockets) == -1)
 54+	if (socketpair(AF_LOCAL, SOCK_SEQPACKET, 0, sock) == -1)
 55 		die("socketpair:");
 56 
 57-	launcher.socket = sockets[0];
 58+	launcher.socket = sock[0];
 59 
 60-	if (fcntl(sockets[0], F_SETFD, FD_CLOEXEC) == -1)
 61+	if (fcntl(sock[0], F_SETFD, FD_CLOEXEC) == -1)
 62 		die("failed set CLOEXEC on socket:");
 63 
 64 	action.sa_handler = &handle_chld;
 65@@ -468,68 +484,35 @@ main(int argc, char *argv[])
 66 	sigprocmask(SIG_SETMASK, &set, NULL);
 67 
 68 	if (!vt) {
 69-		find_vt(vt_buf, sizeof vt_buf);
 70-		vt = vt_buf;
 71+		find_vt(buf, sizeof(buf));
 72+		vt = buf;
 73 	}
 74 
 75 	fprintf(stderr, "running on %s\n", vt);
 76 	launcher.tty_fd = open_tty(vt);
 77 	setup_tty(launcher.tty_fd);
 78 
 79-	child_pid = fork();
 80-
 81-	if (child_pid == 0) {
 82-		char string[64];
 83-
 84-		/* Reset signal handlers to defaults */
 85-		action.sa_handler = SIG_DFL;
 86-		if (sigaction(SIGCHLD, &action, NULL) == -1)
 87-			die("failed to set default signal handler for SIGCHLD:");
 88-		if (sigaction(SIGUSR1, &action, NULL) == -1)
 89-			die("failed to set default signal handler for SIGUSR1:");
 90-		if (sigaction(SIGUSR2, &action, NULL) == -1)
 91-			die("failed to set default signal handler for SIGUSR2:");
 92-		if (sigaction(SIGINT, &action, NULL) == -1)
 93-			die("failed to set default signal handler for SIGINT:");
 94-		if (sigaction(SIGTERM, &action, NULL) == -1)
 95-			die("failed to set default signal handler for SIGTERM:");
 96-
 97-		/* Set empty signal mask */
 98-		sigemptyset(&set);
 99-		sigprocmask(SIG_SETMASK, &set, NULL);
100-
101-		sprintf(string, "%d", sockets[1]);
102-		setenv(SWC_LAUNCH_SOCKET_ENV, string, 1);
103-
104-		sprintf(string, "%d", launcher.tty_fd);
105-		setenv(SWC_LAUNCH_TTY_FD_ENV, string, 1);
106-
107-		if (setuid(getuid()) < 0)
108-			die("setuid:");
109-		if (setgid(getgid()) < 0)
110-			die("setgid:");
111-
112-		execvp(argv[optind], argv + optind);
113-		die("exec %s:", argv[optind]);
114-	} else {
115-		struct pollfd pollfd;
116-		int ret;
117-
118-		pollfd.fd = sockets[0];
119-		pollfd.events = POLLIN;
120-
121-		while (true) {
122-			ret = poll(&pollfd, 1, -1);
123-
124-			if (ret == -1) {
125-				if (errno == EINTR)
126-					continue;
127-				die("poll:");
128-			}
129-
130-			handle_socket_data(pollfd.fd);
131-		}
132-	}
133+	sprintf(buf, "%d", sock[1]);
134+	setenv(SWC_LAUNCH_SOCKET_ENV, buf, 1);
135+	sprintf(buf, "%d", launcher.tty_fd);
136+	setenv(SWC_LAUNCH_TTY_FD_ENV, buf, 1);
137+
138+	if (posix_spawnattr_setflags(&attr, POSIX_SPAWN_RESETIDS | POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK) < 0)
139+		die("failed to set spawnattr flags:");
140+	sigemptyset(&set);
141+	if (posix_spawnattr_setsigmask(&attr, &set) < 0)
142+		die("failed to set spawnattr sigmask:");
143+	sigaddset(&set, SIGCHLD);
144+	sigaddset(&set, SIGUSR1);
145+	sigaddset(&set, SIGUSR2);
146+	sigaddset(&set, SIGINT);
147+	sigaddset(&set, SIGTERM);
148+	if (posix_spawnattr_setsigdefault(&attr, &set) < 0)
149+		die("failed to set spawnattr sigdefault:");
150+	if (posix_spawnp(&child_pid, argv[optind], NULL, &attr, argv + optind, environ) < 0)
151+		die("failed to spawn server:");
152+
153+	run(sock[0]);
154 
155 	return EXIT_SUCCESS;
156 }