/* * Run a task prolog script. Also read the stdout of the script and set * environment variables in the task's environment as specified * in the script's standard output. * name IN: class of program ("system prolog", "user prolog", etc.) * path IN: pathname of program to run * job IN/OUT: pointer to associated job, can update job->env * if prolog * RET 0 on success, -1 on failure. */ static int _run_script_and_set_env(const char *name, const char *path, slurmd_job_t *job) { int status, rc, nread; pid_t cpid; int pfd[2], offset = 0; char buf[4096]; xassert(job->env); if (path == NULL || path[0] == '\0') return 0; debug("[job %u] attempting to run %s [%s]", job->jobid, name, path); if (access(path, R_OK | X_OK) < 0) { error("Could not run %s [%s]: %m", name, path); return -1; } if (pipe(pfd) < 0) { error("executing %s: pipe: %m", name); return -1; } if ((cpid = fork()) < 0) { error("executing %s: fork: %m", name); return -1; } if (cpid == 0) { char *argv[2]; argv[0] = xstrdup(path); argv[1] = NULL; close(1); if (dup(pfd[1]) == -1) error("couldn't do the dup: %m"); close(2); close(0); close(pfd[0]); close(pfd[1]); #ifdef SETPGRP_TWO_ARGS setpgrp(0, 0); #else setpgrp(); #endif execve(path, argv, job->env); error("execve(): %m"); exit(127); } close(pfd[1]); buf[0] = '\0'; while ((nread = read(pfd[0], buf+offset, (sizeof(buf)-offset))) > 0) offset += nread; /* debug ("read %d:%s:", offset, buf); */ _proc_stdout(buf, &job->env); close(pfd[0]); while (1) { rc = waitpid(cpid, &status, 0); if (rc < 0) { if (errno == EINTR) continue; error("waidpid: %m"); return 0; } else { killpg(cpid, SIGKILL); /* kill children too */ return status; } } /* NOTREACHED */ }
/* * Run a task prolog script. Also read the stdout of the script and set * environment variables in the task's environment as specified * in the script's standard output. * name IN: class of program ("system prolog", "user prolog", etc.) * path IN: pathname of program to run * job IN/OUT: pointer to associated job, can update job->env * if prolog * RET 0 on success, -1 on failure. */ static int _run_script_and_set_env(const char *name, const char *path, stepd_step_rec_t *job) { int status, rc; pid_t cpid; int pfd[2]; char buf[4096]; FILE *f; xassert(job->env); if (path == NULL || path[0] == '\0') return 0; debug("[job %u] attempting to run %s [%s]", job->jobid, name, path); if (access(path, R_OK | X_OK) < 0) { error("Could not run %s [%s]: %m", name, path); return -1; } if (pipe(pfd) < 0) { error("executing %s: pipe: %m", name); return -1; } if ((cpid = fork()) < 0) { error("executing %s: fork: %m", name); return -1; } if (cpid == 0) { char *argv[2]; argv[0] = xstrdup(path); argv[1] = NULL; if (dup2(pfd[1], 1) == -1) error("couldn't do the dup: %m"); close(2); close(0); close(pfd[0]); close(pfd[1]); setpgid(0, 0); execve(path, argv, job->env); error("execve(%s): %m", path); exit(127); } close(pfd[1]); f = fdopen(pfd[0], "r"); if (f == NULL) { error("Cannot open pipe device: %m"); log_fini(); exit(1); } while (feof(f) == 0) { if (fgets(buf, sizeof(buf) - 1, f) != NULL) { _proc_stdout(buf, job); } } fclose(f); while (1) { rc = waitpid(cpid, &status, 0); if (rc < 0) { if (errno == EINTR) continue; error("waidpid: %m"); return 0; } else { killpg(cpid, SIGKILL); /* kill children too */ return status; } } /* NOTREACHED */ }