46 #include <sys/types.h>
49 #include <sys/resource.h>
61 char safe_process_name[32]= {0};
69 fprintf(stderr,
"%s: ", safe_process_name);
71 vfprintf(stderr, fmt, args);
72 fprintf(stderr,
"\n");
78 static void die(
const char* fmt, ...)
81 fprintf(stderr,
"%s: FATAL ERROR, ", safe_process_name);
83 vfprintf(stderr, fmt, args);
84 fprintf(stderr,
"\n");
86 if (
int last_err= errno)
87 fprintf(stderr,
"error: %d, %s\n", last_err, strerror(last_err));
92 static void kill_child(
void)
96 message(
"Killing child: %d", child_pid);
98 kill(-child_pid, SIGKILL);
100 pid_t ret_pid= waitpid(child_pid, &status, 0);
101 if (ret_pid == child_pid)
104 if (WIFEXITED(status))
107 exit_code= WEXITSTATUS(status);
108 message(
"Child exit: %d", exit_code);
113 if (WIFSIGNALED(status))
114 message(
"Child killed by signal: %d", WTERMSIG(status));
122 extern "C" void handle_abort(
int sig)
124 message(
"Got signal %d, child_pid: %d, sending ABRT", sig, child_pid);
127 kill (-child_pid, SIGABRT);
132 extern "C" void handle_signal(
int sig)
134 message(
"Got signal %d, child_pid: %d", sig, child_pid);
141 signal(SIGTERM, SIG_IGN);
142 signal(SIGINT, SIG_IGN);
149 int main(
int argc,
char*
const argv[] )
151 char*
const* child_argv= 0;
152 pid_t own_pid= getpid();
153 pid_t parent_pid= getppid();
157 sa.sa_handler= handle_signal;
158 sa.sa_flags= SA_NOCLDSTOP;
159 sigemptyset(&sa.sa_mask);
161 sa_abort.sa_handler= handle_abort;
162 sigemptyset(&sa_abort.sa_mask);
169 sprintf(safe_process_name,
"safe_process[%ld]", (
long) own_pid);
174 for (
int i= 1;
i < argc;
i++) {
175 const char* arg= argv[
i];
176 if (strcmp(arg,
"--") == 0 && strlen(arg) == 2) {
179 die(
"No real args -> nothing to do");
180 child_argv= &argv[
i+1];
183 if ( strcmp(arg,
"--verbose") == 0 )
185 else if ( strncmp(arg,
"--parent-pid", 12) == 0 )
189 if ((start= strstr(arg,
"=")) == NULL)
190 die(
"Could not find start of option value in '%s'", arg);
192 if ((parent_pid= atoi(start)) == 0)
193 die(
"Invalid value '%s' passed to --parent-id", start);
195 else if ( strcmp(arg,
"--nocore") == 0 )
199 else if ( strncmp (arg,
"--env ", 6) == 0 )
201 putenv(strdup(arg+6));
204 die(
"Unknown option: %s", arg);
207 if (!child_argv || *child_argv == 0)
208 die(
"nothing to do");
210 message(
"parent_pid: %d", parent_pid);
211 if (parent_pid == own_pid)
212 die(
"parent_pid is equal to own pid!");
217 die(
"Failed to create pipe");
220 while((child_pid= fork()) == -1)
231 signal(SIGTERM, SIG_DFL);
232 signal(SIGINT, SIG_DFL);
233 signal(SIGCHLD, SIG_DFL);
241 struct rlimit corelim = { 0, 0 };
242 if (setrlimit (RLIMIT_CORE, &corelim) < 0)
244 message(
"setrlimit failed, errno=%d", errno);
250 if ((write(pfd[1], &buf, 1)) < 1)
251 die(
"Failed to signal that child is ready");
255 if (execvp(child_argv[0], child_argv) < 0)
256 die(
"Failed to exec child");
262 if ((read(pfd[0], &buf, 1)) < 1)
263 die(
"Failed to read signal from child");
266 die(
"Didn't get 37 from pipe");
270 message(
"Started child %d, terminated: %d", child_pid, terminated);
275 if (
kill(parent_pid, 0) != 0){
276 message(
"Parent is not alive anymore");
283 pid_t ret_pid= waitpid(child_pid, &status, WNOHANG);
284 if (ret_pid == child_pid)
287 if (WIFEXITED(status))
290 ret_code= WEXITSTATUS(status);
291 message(
"Child exit: %d", ret_code);
296 if (WIFSIGNALED(status))
297 message(
"Child killed by signal: %d", WTERMSIG(status));