7 #include <sys/prctl.h> // prctl(), PR_SET_PDEATHSIG
20 child_record_t *children = NULL;
23 child_handler (int sig)
28 while ((pid = waitpid (-1, &status, WNOHANG)) > 0)
31 printf ("fateshare: pid %d quit with status %d\n", pid, status);
32 for (i = 0; i < n_children; i++)
34 if (children[i].pid == pid)
43 term_handler (int sig)
47 printf ("fateshare: terminating!\n");
48 for (i = 0; i < n_children; i++)
50 kill (-children[i].pid, SIGTERM);
60 printf ("fateshare: terminating all the child processes!\n");
61 for (i = 0; i < n_children; i++)
63 kill (-children[i].pid, SIGTERM);
68 launch_command (char *scmd, char *logname_base)
70 pid_t ppid_before_fork = getpid ();
85 int r = prctl (PR_SET_PDEATHSIG, SIGTERM);
92 if (getppid () != ppid_before_fork)
98 int r1 = setpgid (getpid (), 0);
101 perror ("setpgid error");
106 int fd = open ("/dev/null", O_RDONLY);
117 fd = open ("/dev/null", O_RDONLY);
125 char logname_stdout[PATH_MAX];
126 char logname_stderr[PATH_MAX];
128 snprintf (logname_stdout, PATH_MAX - 1, "%s-stdout.txt", logname_base);
129 snprintf (logname_stderr, PATH_MAX - 1, "%s-stderr.txt", logname_base);
131 printf ("LOG STDOUT %s: %s\n", scmd, logname_stdout);
132 printf ("LOG STDERR %s: %s\n", scmd, logname_stderr);
134 fd = open ((char *) logname_stdout, O_APPEND | O_RDWR | O_CREAT, 0777);
141 fd = open ((char *) logname_stderr, O_APPEND | O_RDWR | O_CREAT, 0777);
149 char *argv[] = { (char *) scmd, 0 };
150 int res = execv (argv[0], argv);
161 main (int argc, char **argv)
163 pid_t ppid = getppid ();
167 printf ("usage: %s <parent_pid> <logfile-basename>\n", argv[0]);
171 pid_t parent_pid = strtoll (argv[1], &errptr, 10);
172 char *logname_base = argv[2];
174 printf ("DEBUG: pid %d starting for parent pid %d\n", getpid (), ppid);
175 printf ("DEBUG: parent pid: %d\n", parent_pid);
176 printf ("DEBUG: base log name: %s\n", logname_base);
179 printf ("%s is not a valid parent pid\n", errptr);
183 int r = prctl (PR_SET_PDEATHSIG, SIGTERM);
190 /* Establish handler. */
192 sigemptyset (&sa.sa_mask);
194 sa.sa_handler = child_handler;
196 sigaction (SIGCHLD, &sa, NULL);
198 sigemptyset (&sa.sa_mask);
200 sa.sa_handler = term_handler;
202 sigaction (SIGTERM, &sa, NULL);
204 sigemptyset (&sa.sa_mask);
206 sa.sa_handler = hup_handler;
208 sigaction (SIGHUP, &sa, NULL);
210 if (getppid () != parent_pid)
212 printf ("parent process unexpectedly finished\n");
216 argc -= 3; /* skip over argv0, ppid, and log base */
220 printf ("DEBUG: total %d children\n", n_children);
221 children = calloc (n_children, sizeof (children[0]));
222 for (i = 0; i < n_children; i++)
224 /* argv persists, so we can just use that pointer */
225 children[i].cmd = argv[i];
226 children[i].pid = launch_command (children[i].cmd, logname_base);
227 printf ("DEBUG: child %d (%s): initial launch pid %d\n", i,
228 children[i].cmd, children[i].pid);
234 pid_t curr_ppid = getppid ();
235 printf ("pid: %d, current ppid %d, original ppid %d\n", getpid (),
237 if (curr_ppid != ppid)
239 printf ("current ppid %d != original ppid %d - force quit\n",
245 for (i = 0; i < n_children; i++)
247 if (children[i].pid == 0)
249 printf ("child %s exited, restarting\n", children[i].cmd);
251 children[i].pid = launch_command (children[i].cmd, logname_base);