Skip to contentSkip to conversation

Start external programs from a separate process

PATCH Applied Alan Jenkins 1 participant 1 message Oct 22, 2008

lore
Share & tools
lore
#0 lore raw

PATCH 2/4 Start external programs from a separate process

Do-not-merge: The timeout for hanging processes is untested

udev/Makefile.am +1 -0
index c374942..2b35bd9 100644
@@ -18,6 +18,7 @@ common_files = \
 	udev-event.c \
 	udev-node.c \
 	udev-rules.c \
+	udev-exec.c \
 	udev-util.c \
 	lib/libudev.h \
 	lib/libudev-private.h \
udev/test-udev.c +3 -7
index 7604513..929f752 100644
@@ -60,6 +60,9 @@ int main(int argc, char *argv[])
 	info(udev, "version %s\n", VERSION);
 	udev_selinux_init(udev);
 
+	/* fork exec daemon before opening fds or changing signal handling */
+	udev_exec_init(udev);
+
 	/* set signal handlers */
 	memset(&act, 0x00, sizeof(act));
 	act.sa_handler = (void (*)(int)) sig_handler;
@@ -69,9 +72,6 @@ int main(int argc, char *argv[])
 	sigaction(SIGINT, &act, NULL);
 	sigaction(SIGTERM, &act, NULL);
 
-	/* trigger timeout to prevent hanging processes */
-	alarm(UDEV_EVENT_TIMEOUT);
-
 	action = getenv("ACTION");
 	devpath = getenv("DEVPATH");
 	subsystem = getenv("SUBSYSTEM");
@@ -99,10 +99,6 @@ int main(int argc, char *argv[])
 	event = udev_event_new(dev);
 	err = udev_event_execute_rules(event, rules);
 
-	/* rules may change/disable the timeout */
-	if (udev_device_get_event_timeout(dev) >= 0)
-		alarm(udev_device_get_event_timeout(dev));
-
 	if (err = 0 && !event->ignore_device && udev_get_run(udev))
 		udev_event_execute_run(event);
 
udev/udev-event.c +1 -1
index 05bb022..99e2995 100644
@@ -731,7 +731,7 @@ int udev_event_execute_run(struct udev_event *event)
 			util_strlcpy(program, cmd, sizeof(program));
 			udev_event_apply_format(event, program, sizeof(program));
 			envp = udev_device_get_properties_envp(event->dev);
-			if (util_run_program(event->udev, program, envp, NULL, 0, NULL) != 0) {
+			if (udev_exec(event->dev, program, NULL, 0, NULL) != 0) {
 				if (!udev_list_entry_get_flag(list_entry))
 					err = -1;
 			}
udev/udev-exec.c new file +594 -0

594 lines not on this page · raw message

udev/udev-rules.c +2 -6
index 32eed78..14f25f5 100644
@@ -284,13 +284,11 @@ static int import_file_into_env(struct udev_device *dev, const char *filename)
 static int import_program_into_env(struct udev_device *dev, const char *program)
 {
 	struct udev *udev = udev_device_get_udev(dev);
-	char **envp;
 	char result[2048];
 	size_t reslen;
 	char *line;
 
-	envp = udev_device_get_properties_envp(dev);
-	if (util_run_program(udev, program, envp, result, sizeof(result), &reslen) != 0)
+	if (udev_exec(dev, program, result, sizeof(result), &reslen) != 0)
 		return -1;
 
 	line = result;
@@ -684,13 +682,11 @@ try_parent:
 	/* execute external program */
 	if (rule->program.operation != KEY_OP_UNSET) {
 		char program[UTIL_PATH_SIZE];
-		char **envp;
 		char result[UTIL_PATH_SIZE];
 
 		util_strlcpy(program, key_val(rule, &rule->program), sizeof(program));
 		udev_event_apply_format(event, program, sizeof(program));
-		envp = udev_device_get_properties_envp(dev);
-		if (util_run_program(event->udev, program, envp, result, sizeof(result), NULL) != 0) {
+		if (udev_exec(event->dev, program, result, sizeof(result), NULL) != 0) {
 			dbg(event->udev, "PROGRAM is false\n");
 			event->program_result[0] = '\0';
 			if (rule->program.operation != KEY_OP_NOMATCH)
udev/udev-util.c +0 -213

222 lines not on this page · raw message

udev/udev.h +5 -2
index 89f6f11..fd3c73d 100644
@@ -104,14 +104,17 @@ extern int udev_node_add(struct udev_device *dev, mode_t mode, const char *owner
 extern int udev_node_remove(struct udev_device *dev, int test);
 extern void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev_old, int test);
 
+/* udev-exec.c */
+extern int udev_exec_init(struct udev *udev);
+extern int udev_exec(struct udev_device *dev, const char *command,
+		     char *result, size_t ressize, size_t *reslen);
+
 /* udev-util.c */
 extern int util_create_path(struct udev *udev, const char *path);
 extern int util_delete_path(struct udev *udev, const char *path);
 extern int util_unlink_secure(struct udev *udev, const char *filename);
 extern uid_t util_lookup_user(struct udev *udev, const char *user);
 extern gid_t util_lookup_group(struct udev *udev, const char *group);
-extern int util_run_program(struct udev *udev, const char *command, char **envp,
-			    char *result, size_t ressize, size_t *reslen);
 
 /* udev-selinux.c */
 #ifndef USE_SELINUX
udev/udevd.c +7 -11
index 21fd6f8..a2c4230 100644
@@ -208,16 +208,9 @@ static void event_fork(struct udev_event *event)
 		sigaction(SIGCHLD, &act, NULL);
 		sigaction(SIGHUP, &act, NULL);
 
-		/* set timeout to prevent hanging processes */
-		alarm(UDEV_EVENT_TIMEOUT);
-
 		/* apply rules, create node, symlinks */
 		err = udev_event_execute_rules(event, rules);
 
-		/* rules may change/disable the timeout */
-		if (udev_device_get_event_timeout(event->dev) >= 0)
-			alarm(udev_device_get_event_timeout(event->dev));
-
 		/* execute RUN= */
 		if (err = 0 && !event->ignore_device && udev_get_run(event->udev))
 			udev_event_execute_run(event);
@@ -699,6 +692,13 @@ int main(int argc, char *argv[])
 	if (write(STDERR_FILENO, 0, 0) < 0)
 		dup2(fd, STDERR_FILENO);
 
+	chdir("/");
+	umask(022);
+	setsid();
+
+	/* fork exec daemon before opening more fds or changing signal handling */
+	udev_exec_init(udev);
+
 	/* init control socket, bind() ensures, that only one udevd instance is running */
 	udev_ctrl = udev_ctrl_new_from_socket(udev, UDEV_CTRL_SOCK_PATH);
 	if (udev_ctrl = NULL) {
@@ -791,10 +791,6 @@ int main(int argc, char *argv[])
 	/* set scheduling priority for the daemon */
 	setpriority(PRIO_PROCESS, 0, UDEVD_PRIORITY);
 
-	chdir("/");
-	umask(022);
-	setsid();
-
 	/* OOM_DISABLE = -17 */
 	fd = open("/proc/self/oom_adj", O_RDWR);
 	if (fd < 0)