void setup_engine(int parallel) { static int already_setup = 0; if (!already_setup) { setup_meta(); if (parallel) setup_all_signals(parallel_handler, parallel_handler); else setup_all_signals(SigHandler, SIG_DFL); already_setup = 1; } }
/*- *----------------------------------------------------------------------- * JobExec -- * Execute the shell for the given job. Called from JobStart * * Side Effects: * A shell is executed, outputs is altered and the Job structure added * to the job table. *----------------------------------------------------------------------- */ static void JobExec(Job *job) { pid_t cpid; /* ID of new child */ struct job_pid *p; int fds[4]; int *fdout = fds; int *fderr = fds+2; int i; banner(job, stdout); setup_engine(1); /* Create the pipe by which we'll get the shell's output. */ if (pipe(fdout) == -1) Punt("Cannot create pipe: %s", strerror(errno)); if (pipe(fderr) == -1) Punt("Cannot create pipe: %s", strerror(errno)); block_signals(); if ((cpid = fork()) == -1) { Punt("Cannot fork"); unblock_signals(); } else if (cpid == 0) { supervise_jobs = false; /* standard pipe code to route stdout and stderr */ close(fdout[0]); if (dup2(fdout[1], 1) == -1) Punt("Cannot dup2(outPipe): %s", strerror(errno)); if (fdout[1] != 1) close(fdout[1]); close(fderr[0]); if (dup2(fderr[1], 2) == -1) Punt("Cannot dup2(errPipe): %s", strerror(errno)); if (fderr[1] != 2) close(fderr[1]); /* * We want to switch the child into a different process family * so we can kill it and all its descendants in one fell swoop, * by killing its process family, but not commit suicide. */ (void)setpgid(0, getpid()); if (random_delay) if (!(nJobs == 1 && no_jobs_left())) usleep(random() % random_delay); setup_all_signals(SigHandler, SIG_DFL); unblock_signals(); /* this exits directly */ run_gnode_parallel(job->node); /*NOTREACHED*/ } else { supervise_jobs = true; job->pid = cpid; /* we set the current position in the buffers to the beginning * and mark another stream to watch in the outputs mask */ for (i = 0; i < 2; i++) prepare_pipe(&job->in[i], fds+2*i); } /* * Now the job is actually running, add it to the table. */ nJobs++; Lst_AtEnd(&runningJobs, job); if (job->flags & JOB_IS_EXPENSIVE) expensive_job = true; p = emalloc(sizeof(struct job_pid)); p->pid = cpid; Lst_AtEnd(&job_pids, p); job->p = Lst_Last(&job_pids); unblock_signals(); if (DEBUG(JOB)) { LstNode ln; (void)fprintf(stdout, "Running %ld (%s)\n", (long)cpid, job->node->name); for (ln = Lst_First(&job->node->commands); ln != NULL ; ln = Lst_Adv(ln)) fprintf(stdout, "\t%s\n", (char *)Lst_Datum(ln)); (void)fflush(stdout); } }