/* PROGRAM: Symposium This program executes a "symposium" for a number of philosophers, by spawning a process per philosopher. */ int Symposium(int argl, void* args) { int bites; /* Bites (mpoykies) per philosopher */ Pid_t pid; int i; assert(argl == sizeof(int[2])); N = ((int*)args)[0]; /* get the arguments */ bites = ((int*)args)[1]; /* Initialize structures */ state = (PHIL*) malloc(sizeof(PHIL)*N); hungry = (CondVar*) malloc(sizeof(CondVar)*N); for(i=0; i<N; i++) { state[i] = NOTHERE; Cond_Init(&(hungry[i])); } /* Execute philosophers */ for(i=0; i<N; i++) { int Arg[2]; Arg[0] = i; Arg[1] = bites; pid = Exec(Philosopher, sizeof(Arg), Arg); } /* Wait for philosophers to exit */ for(i=0; i<N; i++) { pid = WaitChild(NOPROC, NULL); } free(state); free(hungry); return 0; }
int boot_task(int argl, void* args) { /* Just start task Symposium */ Exec(Symposium, argl, args); while( WaitChild(NOPROC, NULL)!=NOPROC ); /* Wait for all children */ return 0; }
/* * This is the initial task, which starts all the other tasks (except for the idle task). */ int boot_task(int argl, void* args) { int i,ntasks,ncalls; int status; long msg; Message m; Pid_t pid; Pid_t printer; Pid_t* pids; ntasks = ((int*)args)[0]; ncalls = ((int*)args)[1]; pids = malloc(sizeof(Pid_t)*ntasks); /* Launch child processes */ printer = Exec(printer_task,0,NULL); ReceivePort(&msg,1); /* Wait until it is ready to print */ for(i=0; i<ntasks; i++) { pids[i] = pid = Exec(fibodriver_task,sizeof(ncalls),&ncalls); printf("boot_task: executed fibodriver %d pid=%d\n",i+1,pid); } /* Wait for child processes */ for(i=0;i<ntasks;i++) { Pid_t pid = WaitChild(NOPROC, &status); printf("boot_task: Process %d exited with exit value %d.\n",pid,status); } /* Tell printer to exit */ m.type = PRINTER_QUIT; m.data = NULL; m.len = 0; SendMail("printer",&m); /* Loop until all children have exited */ while(WaitChild(NOPROC,NULL) != NOPROC) printf("boot_task: child exited.\n"); printf("boot_task: exiting!\n"); return 0; }
/* PROGRAM: fibodriver_task This program creates a fibo_task child and then sends to it a number of values to process. */ int fibodriver_task(int argl, void* args) { int work; Pid_t child; assert(argl == sizeof(int)); work = *((int*)args) ; child = Exec(fibo_task, 0, NULL); while(work>0) { SendPort(child, fiborand()); work --; } SendPort(child, -1); WaitChild(child,NULL); return 0; }
// Run the command specified by the argv array and kill it after timeout // seconds. static void SpawnCommand(char *const *argv, double timeout_secs) { CHECK_CALL(global_child_pid = fork()); if (global_child_pid == 0) { // In child. CHECK_CALL(setsid()); ClearSignalMask(); // Force umask to include read and execute for everyone, to make // output permissions predictable. umask(022); // Does not return unless something went wrong. execvp(argv[0], argv); err(EXIT_FAILURE, "execvp(\"%s\", ...)", argv[0]); } else { // In parent. // Set up a signal handler which kills all subprocesses when the given // signal is triggered. HandleSignal(SIGALRM, OnSignal); HandleSignal(SIGTERM, OnSignal); HandleSignal(SIGINT, OnSignal); SetTimeout(timeout_secs); int status = WaitChild(global_child_pid, argv[0]); // The child is done for, but may have grandchildren that we still have to // kill. kill(-global_child_pid, SIGKILL); if (global_signal > 0) { // Don't trust the exit code if we got a timeout or signal. UnHandle(global_signal); raise(global_signal); } else if (WIFEXITED(status)) { exit(WEXITSTATUS(status)); } else { int sig = WTERMSIG(status); UnHandle(sig); raise(sig); } } }
// Usage: process-wrapper // <timeout_sec> <kill_delay_sec> <stdout file> <stderr file> // [cmdline] int main(int argc, char *argv[]) { if (argc <= 5) { DIE("Not enough cmd line arguments to process-wrapper"); } // Parse the cmdline args to get the timeout and redirect files. argv++; double timeout; if (sscanf(*argv++, "%lf", &timeout) != 1) { DIE("timeout_sec is not a real number."); } if (sscanf(*argv++, "%lf", &global_kill_delay) != 1) { DIE("kill_delay_sec is not a real number."); } char *stdout_path = *argv++; char *stderr_path = *argv++; if (strcmp(stdout_path, "-")) { // Redirect stdout and stderr. int fd_out = open(stdout_path, O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd_out == -1) { DIE("Could not open %s for stdout", stdout_path); } if (dup2(fd_out, STDOUT_FILENO) == -1) { DIE("dup2 failed for stdout"); } CHECK_CALL(close(fd_out)); } if (strcmp(stderr_path, "-")) { int fd_err = open(stderr_path, O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd_err == -1) { DIE("Could not open %s for stderr", stderr_path); } if (dup2(fd_err, STDERR_FILENO) == -1) { DIE("dup2 failed for stderr"); } CHECK_CALL(close(fd_err)); } global_pid = fork(); if (global_pid < 0) { DIE("Fork failed"); } else if (global_pid == 0) { // In child. if (setsid() == -1) { DIE("Could not setsid from child"); } ClearSignalMask(); // Force umask to include read and execute for everyone, to make // output permissions predictable. umask(022); execvp(argv[0], argv); // Does not return. DIE("execvpe %s failed", argv[0]); } else { // In parent. InstallSignalHandler(SIGALRM); InstallSignalHandler(SIGTERM); InstallSignalHandler(SIGINT); EnableAlarm(timeout); int status = WaitChild(global_pid, argv[0]); // The child is done, but may have grandchildren. kill(-global_pid, SIGKILL); if (global_signal > 0) { // Don't trust the exit code if we got a timeout or signal. UnHandle(global_signal); raise(global_signal); } else if (WIFEXITED(status)) { exit(WEXITSTATUS(status)); } else { int sig = WTERMSIG(status); UnHandle(sig); raise(sig); } } }