/*#* multi_fork_exec.c Use with large_image.c to trigger this execve() case: In most cases where execve() fails, control returns to the original executable image, and the caller of execve() can then handle the error. However, in (rare) cases (typically caused by resource exhaustion), failure may occur past the point of no return: the original executable image has been torn down, but the new image could not be completely built. In such cases, the kernel kills the process with a SIGKILL signal. */ /*#** Change history 04 May 14 Initial creation */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ } while (0) static void /* Examine a wait() status using the W* macros */ printWaitStatus(const char *msg, int status) { if (msg != NULL) printf("%s", msg); if (WIFEXITED(status)) { printf("child exited, status=%d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("child killed by signal %d (%s)", WTERMSIG(status), strsignal(WTERMSIG(status))); #ifdef WCOREDUMP /* Not in SUSv3, may be absent on some systems */ if (WCOREDUMP(status)) printf(" (core dumped)"); #endif printf("\n"); } else if (WIFSTOPPED(status)) { printf("child stopped by signal %d (%s)\n", WSTOPSIG(status), strsignal(WSTOPSIG(status))); #ifdef WIFCONTINUED /* SUSv3 has this, but older Linux versions and some other UNIX implementations don't */ } else if (WIFCONTINUED(status)) { printf("child continued\n"); #endif } else { /* Should never happen */ printf("what happened to this child? (status=%x)\n", (unsigned int) status); } } static void /* Handler for child termination signal */ grimReaper(int sig) { int status; /* Child status from waitpid() */ pid_t pid; int savedErrno; savedErrno = errno; while ((pid = waitpid(-1, &status, 0)) > 0) { if (pid == -1) errExit("waitpid"); printf("\tChild PID=%ld\n", (long) pid); printWaitStatus("\tStatus: ", status); } errno = savedErrno; } int main(int argc, char *argv[]) { int cnt; pid_t cpid; struct sigaction sa; /* Set up handler to reap dead children */ sa.sa_flags = 0; sa.sa_handler = grimReaper; sigemptyset(&sa.sa_mask); if (sigaction(SIGCHLD, &sa, NULL) == -1) errExit("sigaction"); /* Create multiple children, each of which execs the program named in argv[1] */ for (cnt = 0; ; cnt++) { printf("cnt = %d\n", cnt); cpid = fork(); if (cpid == -1) errExit("fork"); if (cpid == 0) { /* Child */ execv(argv[1], &argv[1]); errExit("execv"); } /* Parent continues round loop */ } exit(EXIT_SUCCESS); }