8 #include <sys/prctl.h> // prctl(), PR_SET_PDEATHSIG
11 #include <sys/procctl.h>
12 #endif /* __linux__ */
25 child_record_t *children = NULL;
28 child_handler (int sig)
33 while ((pid = waitpid (-1, &status, WNOHANG)) > 0)
36 printf ("fateshare: pid %d quit with status %d\n", pid, status);
37 for (i = 0; i < n_children; i++)
39 if (children[i].pid == pid)
48 term_handler (int sig)
52 printf ("fateshare: terminating!\n");
53 for (i = 0; i < n_children; i++)
55 kill (-children[i].pid, SIGTERM);
65 printf ("fateshare: terminating all the child processes!\n");
66 for (i = 0; i < n_children; i++)
68 kill (-children[i].pid, SIGTERM);
73 launch_command (char *scmd, char *logname_base)
75 pid_t ppid_before_fork = getpid ();
91 int r = prctl (PR_SET_PDEATHSIG, SIGTERM);
101 r = procctl (P_PID, 0, PROC_PDEATHSIG_CTL, &s);
107 #endif /* __linux__ */
109 if (getppid () != ppid_before_fork)
115 int r1 = setpgid (getpid (), 0);
118 perror ("setpgid error");
123 int fd = open ("/dev/null", O_RDONLY);
134 fd = open ("/dev/null", O_RDONLY);
142 char logname_stdout[PATH_MAX];
143 char logname_stderr[PATH_MAX];
145 snprintf (logname_stdout, PATH_MAX - 1, "%s-stdout.txt", logname_base);
146 snprintf (logname_stderr, PATH_MAX - 1, "%s-stderr.txt", logname_base);
148 printf ("LOG STDOUT %s: %s\n", scmd, logname_stdout);
149 printf ("LOG STDERR %s: %s\n", scmd, logname_stderr);
151 fd = open ((char *) logname_stdout, O_APPEND | O_RDWR | O_CREAT, 0777);
158 fd = open ((char *) logname_stderr, O_APPEND | O_RDWR | O_CREAT, 0777);
166 char *argv[] = { (char *) scmd, 0 };
167 int res = execv (argv[0], argv);
178 main (int argc, char **argv)
180 pid_t ppid = getppid ();
184 printf ("usage: %s <parent_pid> <logfile-basename>\n", argv[0]);
188 pid_t parent_pid = strtoll (argv[1], &errptr, 10);
189 char *logname_base = argv[2];
191 printf ("DEBUG: pid %d starting for parent pid %d\n", getpid (), ppid);
192 printf ("DEBUG: parent pid: %d\n", parent_pid);
193 printf ("DEBUG: base log name: %s\n", logname_base);
196 printf ("%s is not a valid parent pid\n", errptr);
201 int r = prctl (PR_SET_PDEATHSIG, SIGTERM);
210 r = procctl (P_PID, 0, PROC_PDEATHSIG_CTL, &s);
216 #endif /* __linux__ */
218 /* Establish handler. */
220 sigemptyset (&sa.sa_mask);
222 sa.sa_handler = child_handler;
224 sigaction (SIGCHLD, &sa, NULL);
226 sigemptyset (&sa.sa_mask);
228 sa.sa_handler = term_handler;
230 sigaction (SIGTERM, &sa, NULL);
232 sigemptyset (&sa.sa_mask);
234 sa.sa_handler = hup_handler;
236 sigaction (SIGHUP, &sa, NULL);
238 if (getppid () != parent_pid)
240 printf ("parent process unexpectedly finished\n");
244 argc -= 3; /* skip over argv0, ppid, and log base */
248 printf ("DEBUG: total %d children\n", n_children);
249 children = calloc (n_children, sizeof (children[0]));
250 for (i = 0; i < n_children; i++)
252 /* argv persists, so we can just use that pointer */
253 children[i].cmd = argv[i];
254 children[i].pid = launch_command (children[i].cmd, logname_base);
255 printf ("DEBUG: child %d (%s): initial launch pid %d\n", i,
256 children[i].cmd, children[i].pid);
262 pid_t curr_ppid = getppid ();
263 printf ("pid: %d, current ppid %d, original ppid %d\n", getpid (),
265 if (curr_ppid != ppid)
267 printf ("current ppid %d != original ppid %d - force quit\n",
273 for (i = 0; i < n_children; i++)
275 if (children[i].pid == 0)
277 printf ("child %s exited, restarting\n", children[i].cmd);
279 children[i].pid = launch_command (children[i].cmd, logname_base);