void execfg(char *cmdarr[MAXCMD][MAXOP],int i) { //Brings the specified background process to the foreground if(cmdarr[i][1] == NULL) { printf("Takes one argument\n"); return; } strcpy(fname,cmdarr[i][0]); int j,temppid = 0; int tempposn = atoi(cmdarr[i][1]); //int tempcnt = 0; for(j=0; j<(MAXNUM*MAXOP); j++) { if(jobsarray[j].count == tempposn && jobsarray[j].state == 1) { temppid = jobsarray[j].pid; break; } } if(temppid > 0) { for(j=0; j<(MAXNUM*MAXOP); j++) { if(jobsarray[j].pid == temppid && jobsarray[j].state == 1) { strcpy(fname,jobsarray[j].name); jobsarray[j].state = 0; fpid = temppid; int temppgid=getpgid(temppid); tcsetpgrp(shell_terminal,temppgid); killpg(temppgid,SIGCONT); int status; do { int w = waitpid(temppid, &status, WUNTRACED | WCONTINUED); if (w == -1) { perror("waitpid"); exit(EXIT_FAILURE); } if (WIFEXITED(status)) { printf("exited, status=%d\n", WEXITSTATUS(status)); break; } else if (WIFSIGNALED(status)) { printf("killed by signal %d\n", WTERMSIG(status)); break; } else if (WIFSTOPPED(status)) { printf("\nstopped by signal %d\n", WSTOPSIG(status)); if(WSTOPSIG(status) == 19 || WSTOPSIG(status) == 20) { strcpy(jobsarray[jobsarraycnt].name,fname); jobsarray[jobsarraycnt].pid = fpid; jobsarray[jobsarraycnt].stopped = 1; jobsarray[jobsarraycnt++].state = 1; } printf("\nstopped by signal %d\n", WSTOPSIG(status)); if(WSTOPSIG(status) == 22) kill(fpid,SIGKILL); break; } else if (WIFCONTINUED(status)) { printf("continued\n"); } } while(!WIFEXITED(status) && !WIFSIGNALED(status)); tcsetpgrp (shell_terminal, shell_pgid); return; } } } printf("No background job with given pid exists\n"); return; }
ProgramWidget::ProgramWidget(Vector2n Position, TypingModule & TypingModule, Project & Project, TextFieldWidget * Target) : FlowLayoutWidget(Position, { std::shared_ptr<Widget>(m_SourceWidget = new ConnectionWidget<TextFieldWidget>(Vector2n::ZERO, Target)), std::shared_ptr<Widget>(new LabelWidget(Vector2n::ZERO, std::string("go run"), LabelWidget::Background::Normal)), std::shared_ptr<Widget>(m_OutputWidget = new TextFieldWidget(Vector2n::ZERO, TypingModule)) }, { std::shared_ptr<Behavior>(new DraggablePositionBehavior(*this)) }), m_Project(Project) { { m_SourceWidget->m_OnChange = [=, &Project]() { //PlayBeep(); Project.m_ProcessEndedTime = glfwGetTime(); Project.m_BackgroundState = 0; // Kill child processes if (0 != Project.m_LastPid) { //std::cout << "Sending kill to last child pid " << Project.m_LastPid << ".\n"; //auto Result = kill(0, SIGTERM); auto Result = killpg(Project.m_LastPid, SIGKILL); //waitpid(m_LastPid, NULL, 0); if (0 != Result) { std::cerr << "Error: kill() failed with return " << Result << ", errno " << errno << ".\n"; //throw 0; } } //std::cout << "Closing " << Project.m_PipeFd[0] << " and " << Project.m_PipeFd[1] << "; "; close(Project.m_PipeFd[0]); // Close the read end of the pipe in the parent Project.m_PipeFd[0] = Project.m_PipeFd[1] = -1; if (!m_SourceWidget->m_LiveToggle->GetState()) { //OutputWidget.m_Visible = false; return; } else { //OutputWidget.m_Visible = true; } std::string Content = ""; if (nullptr != m_SourceWidget->Target()) { Content = m_SourceWidget->Target()->GetContent(); } Project.GenerateProgram(Content); g_OutputWidget = m_OutputWidget; // HACK //m_OutputWidget->SetContent(""); Project.m_ProcessStartedTime = glfwGetTime(); Project.m_ExpiredOutput = true; Project.m_BackgroundState = 1; }; // If there's already a Target for source, then refresh ourselves m_SourceWidget->m_OnChange(); } // TODO: Make this work in LiveProgramWidget too (currently the Cmd+R event doesn't go from LiveProgramWidget to this ProgramWidget) ModifyGestureRecognizer().AddShortcut(GestureRecognizer::ShortcutEntry('R', PointerState::Modifiers::Super, m_SourceWidget->m_OnChange, "Run/Refresh")); m_GetLineAnnotations = [this](uint32 LineNumber) -> std::string { //return std::to_string(LineNumber + 1) + "-" + (m_ProgramWidget->m_OutputWidget->GetContent().length() >= 3 ? m_ProgramWidget->m_OutputWidget->GetContent().substr(0, 3) : "..."); // HACK: Using hardcoded color, make this better // Don't do this if the result is not compile error, or if Live Toggle is off if ( Color(1.0, 0.9, 0.9) != this->m_OutputWidget->GetBackground() || false == this->m_SourceWidget->m_LiveToggle->GetState()) return ""; // TODO: Clean up { std::stringstream ss; auto Input = this->m_OutputWidget->GetContent(); TrimLastNewline(Input); ss << Input; std::string Line; std::getline(ss, Line); // Skip first line for (;;) { std::getline(ss, Line); // Parse one go error line try { auto FirstColon = Line.find(':'); auto SecondColon = Line.find(':', FirstColon + 1); uint32 FoundLineNumber = std::stoi(Line.substr(FirstColon + 1, SecondColon - (FirstColon + 1))); if (FoundLineNumber == LineNumber + 1) return TrimFirstSpace(Line.substr(SecondColon + 1)); } catch (...) {} if (ss.eof()) break; } } return ""; }; }
VALUE rb_f_kill(int argc, VALUE *argv) { #ifndef HAVE_KILLPG #define killpg(pg, sig) kill(-(pg), (sig)) #endif int negative = 0; int sig; int i; volatile VALUE str; const char *s; rb_secure(2); rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS); switch (TYPE(argv[0])) { case T_FIXNUM: sig = FIX2INT(argv[0]); break; case T_SYMBOL: s = rb_id2name(SYM2ID(argv[0])); if (!s) rb_raise(rb_eArgError, "bad signal"); goto str_signal; case T_STRING: s = RSTRING_PTR(argv[0]); str_signal: if (s[0] == '-') { negative++; s++; } if (strncmp("SIG", s, 3) == 0) s += 3; if ((sig = signm2signo(s)) == 0) rb_raise(rb_eArgError, "unsupported name `SIG%s'", s); if (negative) sig = -sig; break; default: str = rb_check_string_type(argv[0]); if (!NIL_P(str)) { s = RSTRING_PTR(str); goto str_signal; } rb_raise(rb_eArgError, "bad signal type %s", rb_obj_classname(argv[0])); break; } if (sig < 0) { sig = -sig; for (i=1; i<argc; i++) { if (killpg(NUM2PIDT(argv[i]), sig) < 0) rb_sys_fail(0); } } else { for (i=1; i<argc; i++) { if (kill(NUM2PIDT(argv[i]), sig) < 0) rb_sys_fail(0); } } return INT2FIX(i-1); }
static int _handle_signal_process_group(int fd, slurmd_job_t *job, uid_t uid) { int rc = SLURM_SUCCESS; int signal; debug3("_handle_signal_process_group for job %u.%u", job->jobid, job->stepid); safe_read(fd, &signal, sizeof(int)); debug3(" uid = %d", uid); if (uid != job->uid && !_slurm_authorized_user(uid)) { debug("kill req from uid %ld for job %u.%u owned by uid %ld", (long)uid, job->jobid, job->stepid, (long)job->uid); rc = EPERM; goto done; } /* * Sanity checks */ if (job->pgid <= (pid_t)1) { debug ("step %u.%u invalid [jmgr_pid:%d pgid:%u]", job->jobid, job->stepid, job->jmgr_pid, job->pgid); rc = ESLURMD_JOB_NOTRUNNING; goto done; } /* * Signal the process group */ pthread_mutex_lock(&suspend_mutex); if (suspended && (signal != SIGKILL)) { rc = ESLURMD_STEP_SUSPENDED; pthread_mutex_unlock(&suspend_mutex); goto done; } /* * Print a message in the step output before killing when * SIGTERM or SIGKILL are sent */ if ((signal == SIGTERM) || (signal == SIGKILL)) { time_t now = time(NULL); char entity[24], time_str[24]; if (job->stepid == SLURM_BATCH_SCRIPT) { snprintf(entity, sizeof(entity), "JOB %u", job->jobid); } else { snprintf(entity, sizeof(entity), "STEP %u.%u", job->jobid, job->stepid); } slurm_make_time_str(&now, time_str, sizeof(time_str)); error("*** %s KILLED AT %s WITH SIGNAL %u ***", entity, time_str, signal); } if (killpg(job->pgid, signal) == -1) { rc = -1; verbose("Error sending signal %d to %u.%u, pgid %d: %m", signal, job->jobid, job->stepid, job->pgid); } else { verbose("Sent signal %d to %u.%u, pgid %d", signal, job->jobid, job->stepid, job->pgid); } pthread_mutex_unlock(&suspend_mutex); done: /* Send the return code */ safe_write(fd, &rc, sizeof(int)); return SLURM_SUCCESS; rwfail: return SLURM_FAILURE; }
void job_continue(job_t *j, int cont) { /* Put job first in the job list */ job_promote(j); job_set_flag(j, JOB_NOTIFIED, 0); CHECK_BLOCK(); debug(4, L"Continue job %d, gid %d (%ls), %ls, %ls", j->job_id, j->pgid, j->command_wcstr(), job_is_completed(j)?L"COMPLETED":L"UNCOMPLETED", is_interactive?L"INTERACTIVE":L"NON-INTERACTIVE"); if (!job_is_completed(j)) { if (job_get_flag(j, JOB_TERMINAL) && job_get_flag(j, JOB_FOREGROUND)) { /* Put the job into the foreground. */ int ok; signal_block(); ok = terminal_give_to_job(j, cont); signal_unblock(); if (!ok) return; } /* Send the job a continue signal, if necessary. */ if (cont) { process_t *p; for (p=j->first_process; p; p=p->next) p->stopped=0; if (job_get_flag(j, JOB_CONTROL)) { if (killpg(j->pgid, SIGCONT)) { wperror(L"killpg (SIGCONT)"); return; } } else { for (p=j->first_process; p; p=p->next) { if (kill(p->pid, SIGCONT) < 0) { wperror(L"kill (SIGCONT)"); return; } } } } if (job_get_flag(j, JOB_FOREGROUND)) { int quit = 0; /* Wait for job to report. Looks a bit ugly because it has to handle the possibility that a signal is dispatched while running job_is_stopped(). */ while (!quit) { do { got_signal = 0; quit = job_is_stopped(j) || job_is_completed(j); } while (got_signal && !quit); if (!quit) { // debug( 1, L"select_try()" ); switch (select_try(j)) { case 1: { read_try(j); break; } case -1: { /* If there is no funky IO magic, we can use waitpid instead of handling child deaths through signals. This gives a rather large speed boost (A factor 3 startup time improvement on my 300 MHz machine) on short-lived jobs. */ int status; pid_t pid = waitpid(-1, &status, WUNTRACED); if (pid > 0) { handle_child_status(pid, status); } else { /* This probably means we got a signal. A signal might mean that the terminal emulator sent us a hup signal to tell is to close. If so, we should exit. */ if (reader_exit_forced()) { quit = 1; } } break; } } } } } } if (job_get_flag(j, JOB_FOREGROUND)) { if (job_is_completed(j)) { // It's possible that the job will produce output and exit before we've even read from it. // We'll eventually read the output, but it may be after we've executed subsequent calls // This is why my prompt colors kept getting screwed up - the builtin echo calls // were sometimes having their output combined with the set_color calls in the wrong order! read_try(j); process_t *p = j->first_process; while (p->next) p = p->next; if (WIFEXITED(p->status) || WIFSIGNALED(p->status)) { /* Mark process status only if we are in the foreground and the last process in a pipe, and it is not a short circuted builtin */ if (p->pid) { int status = proc_format_status(p->status); //wprintf(L"setting status %d for %ls\n", job_get_flag( j, JOB_NEGATE )?!status:status, j->command); proc_set_last_status(job_get_flag(j, JOB_NEGATE)?!status:status); } } } /* Put the shell back in the foreground. */ if (job_get_flag(j, JOB_TERMINAL) && job_get_flag(j, JOB_FOREGROUND)) { int ok; signal_block(); ok = terminal_return_from_job(j); signal_unblock(); if (!ok) return; } } }
/*---------------------------------------------------------------------------*/ void matar_procesos_propios() { killpg(getpgrp(),SIGINT); killpg(getpgrp(),SIGQUIT); killpg(getpgrp(),SIGKILL); }
/* * Exit codes: * 0 - everything went OK (might be CPU, MEM, or FILE limit exceeded!) * 1 - I was not invoked correctly * 2 - I can't fork * 3 - I can't execute * 4 - wall time expired, I had to abort */ int main(int argc, char* argv[]) { int i; int child; int status; int tle; struct rlimit cpu, mem, file, fcnt; int wall; struct timeval start_time, current_time; char* cmd; int sec, usec; // elapsed wall time /* defaults */ wall = 180; // 3 minutes cpu.rlim_cur = 60; // 1 minute mem.rlim_cur = 512; // half a giga file.rlim_cur = 1 << 14; // 16 MB fcnt.rlim_cur = fcnt.rlim_max = 128; // no need for more open files /* parse arguments */ if (!(argc&1)) usage(); cmd = NULL; for (i = 1; i + 1 < argc; i += 2) { if (!strcmp("-m", argv[i])) sscanf(argv[i+1], "%d", &mem.rlim_cur); else if (!strcmp("-c", argv[i])) sscanf(argv[i+1], "%d", &cpu.rlim_cur); else if (!strcmp("-w", argv[i])) sscanf(argv[i+1], "%d", &wall); else if (!strcmp("-f", argv[i])) sscanf(argv[i+1], "%d", &file.rlim_cur); else if (!strcmp("-x", argv[i])) cmd = argv[i+1]; else usage(); } if (cmd == NULL) usage(); if (wall > cpu.rlim_cur) wall = cpu.rlim_cur; mem.rlim_cur <<= 20; // MB file.rlim_cur <<= 10; // KB cpu.rlim_max = cpu.rlim_cur; mem.rlim_max = mem.rlim_cur; file.rlim_max = file.rlim_cur; /* set limits */ setrlimit(RLIMIT_CPU, &cpu); setrlimit(RLIMIT_AS, &mem); setrlimit(RLIMIT_FSIZE, &file); setrlimit(RLIMIT_NOFILE, &fcnt); /* start the child */ child = fork(); if (child == -1) { fprintf(stderr, "can't fork."); return 2; } if (child == 0) { setsid(); execl("/bin/sh", "sh", "-c", cmd, (char*)0); perror("Can't execute"); return 3; } /* watch out for wall time limit */ gettimeofday(&start_time, NULL); while (!waitpid(child, &status, WNOHANG)) { usleep(25000); gettimeofday(¤t_time, NULL); sec = current_time.tv_sec - start_time.tv_sec; usec = current_time.tv_usec - start_time.tv_usec; if (sec > wall || (sec == wall && usec > 0)) { fprintf(stderr, "Hanged\n"); if (killpg(child, SIGKILL)) fprintf(stderr, "Failed to kill"); } usleep(50000); } if (WIFSIGNALED(status)) return 4; return 0; }
int main(int argc, char *argv[]) { int ch; char *caldir; (void)setlocale(LC_ALL, ""); while ((ch = getopt(argc, argv, "abf:t:A:B:-")) != -1) switch (ch) { case '-': /* backward contemptible */ case 'a': if (getuid()) errx(1, "%s", strerror(EPERM)); doall = 1; break; case 'b': bodun_always++; break; case 'f': /* other calendar file */ calendarFile = optarg; break; case 't': /* other date, undocumented, for tests */ if ((f_time = Mktime(optarg)) <= 0) errx(1, "specified date is outside allowed range"); break; case 'A': /* days after current date */ f_dayAfter = atoi(optarg); f_SetdayAfter = 1; break; case 'B': /* days before current date */ f_dayBefore = atoi(optarg); break; default: usage(); } argc -= optind; argv += optind; if (argc) usage(); /* use current time */ if (f_time <= 0) (void)time(&f_time); if (f_dayBefore) { /* Move back in time and only look forwards */ f_dayAfter += f_dayBefore; f_time -= SECSPERDAY * f_dayBefore; f_dayBefore = 0; } settime(&f_time); if (doall) { pid_t kid, deadkid; int kidstat, kidreaped, runningkids; int acstat; struct stat sbuf; time_t t; unsigned int sleeptime; signal(SIGCHLD, childsig); runningkids = 0; t = time(NULL); while ((pw = getpwent()) != NULL) { acstat = 0; /* Avoid unnecessary forks. The calendar file is only * opened as the user later; if it can't be opened, * it's no big deal. Also, get to correct directory. * Note that in an NFS environment root may get EACCES * on a chdir(), in which case we have to fork. As long as * we can chdir() we can stat(), unless the user is * modifying permissions while this is running. */ if (chdir(pw->pw_dir)) { if (errno == EACCES) acstat = 1; else continue; } if (stat(calendarFile, &sbuf) != 0) { if (chdir(calendarHome)) { if (errno == EACCES) acstat = 1; else continue; } if (stat(calendarNoMail, &sbuf) == 0 || stat(calendarFile, &sbuf) != 0) continue; } sleeptime = USERTIMEOUT; switch ((kid = fork())) { case -1: /* error */ warn("fork"); continue; case 0: /* child */ (void)setpgid(getpid(), getpid()); (void)setlocale(LC_ALL, ""); if (setusercontext(NULL, pw, pw->pw_uid, LOGIN_SETALL ^ LOGIN_SETLOGIN)) err(1, "unable to set user context (uid %u)", pw->pw_uid); if (acstat) { if (chdir(pw->pw_dir) || stat(calendarFile, &sbuf) != 0 || chdir(calendarHome) || stat(calendarNoMail, &sbuf) == 0 || stat(calendarFile, &sbuf) != 0) exit(0); } cal(); exit(0); } /* parent: wait a reasonable time, then kill child if * necessary. */ runningkids++; kidreaped = 0; do { sleeptime = sleep(sleeptime); /* Note that there is the possibility, if the sleep * stops early due to some other signal, of the child * terminating and not getting detected during the next * sleep. In that unlikely worst case, we just sleep * too long for that user. */ for (;;) { deadkid = waitpid(-1, &kidstat, WNOHANG); if (deadkid <= 0) break; runningkids--; if (deadkid == kid) { kidreaped = 1; sleeptime = 0; } } } while (sleeptime); if (!kidreaped) { /* It doesn't _really_ matter if the kill fails, e.g. * if there's only a zombie now. */ if (getpgid(kid) != getpgrp()) (void)killpg(getpgid(kid), SIGTERM); else (void)kill(kid, SIGTERM); warnx("uid %u did not finish in time", pw->pw_uid); } if (time(NULL) - t >= SECSPERDAY) errx(2, "'calendar -a' took more than a day; " "stopped at uid %u", pw->pw_uid); } for (;;) { deadkid = waitpid(-1, &kidstat, WNOHANG); if (deadkid <= 0) break; runningkids--; } if (runningkids) warnx("%d child processes still running when " "'calendar -a' finished", runningkids); } else if ((caldir = getenv("CALENDAR_DIR")) != NULL) { if(!chdir(caldir)) cal(); } else cal(); exit(0); }
/* Execute a script, wait for termination and return its stdout. * script_name IN - Name of program being run (e.g. "StartStageIn") * script_path IN - Fully qualified program of the program to execute * script_args IN - Arguments to the script * max_wait IN - Maximum time to wait in milliseconds, * -1 for no limit (asynchronous) * data_in IN - data to use as program STDIN (NULL if not STDIN) * status OUT - Job exit code * Return stdout+stderr of spawned program, value must be xfreed. */ extern char *power_run_script(char *script_name, char *script_path, char **script_argv, int max_wait, char *data_in, int *status) { int i, new_wait, resp_size = 0, resp_offset = 0; int send_size = 0, send_offset = 0; pid_t cpid; char *resp = NULL; int fd_stdout[2] = { -1, -1 }; int fd_stdin[2] = { -1, -1 }; if ((script_path == NULL) || (script_path[0] == '\0')) { error("%s: no script specified", __func__); *status = 127; resp = xstrdup("Slurm burst buffer configuration error"); return resp; } if (slurm_get_debug_flags() & DEBUG_FLAG_POWER) { for (i = 0; i < 10; i++) { if (!script_argv[i]) break; } if (i == 0) { info("%s:", __func__); } else if (i == 1) { info("%s: %s", __func__, script_name); } else if (i == 2) { info("%s: %s %s", __func__, script_name, script_argv[1]); } else if (i == 3) { info("%s: %s %s %s", __func__, script_name, script_argv[1], script_argv[2]); } else if (i == 4) { info("%s: %s %s %s %s", __func__, script_name, script_argv[1], script_argv[2], script_argv[3]); } else if (i == 5) { info("%s: %s %s %s %s %s", __func__, script_name, script_argv[1], script_argv[2], script_argv[3], script_argv[4]); } else if (i == 6) { info("%s: %s %s %s %s %s %s", __func__, script_name, script_argv[1], script_argv[2], script_argv[3], script_argv[4], script_argv[5]); } else if (i == 7) { info("%s: %s %s %s %s %s %s %s", __func__, script_name, script_argv[1], script_argv[2], script_argv[3], script_argv[4], script_argv[5], script_argv[6]); } else { /* 8 or more args here, truncate as needed */ info("%s: %s %s %s %s %s %s %s %s", __func__, script_name, script_argv[1], script_argv[2], script_argv[3], script_argv[4], script_argv[5], script_argv[6], script_argv[7]); } if (data_in) info("%s: %s", __func__, data_in); } if (script_path[0] != '/') { error("%s: %s is not fully qualified pathname (%s)", __func__, script_name, script_path); *status = 127; resp = xstrdup("Slurm burst buffer configuration error"); return resp; } if (access(script_path, R_OK | X_OK) < 0) { error("%s: %s can not be executed (%s) %m", __func__, script_name, script_path); *status = 127; resp = xstrdup("Slurm burst buffer configuration error"); return resp; } if (data_in) { if (pipe(fd_stdin) != 0) { error("%s: pipe(): %m", __func__); *status = 127; resp = xstrdup("System error"); return resp; } } if (max_wait != -1) { if (pipe(fd_stdout) != 0) { error("%s: pipe(): %m", __func__); *status = 127; resp = xstrdup("System error"); return resp; } } if ((cpid = fork()) == 0) { int cc; cc = sysconf(_SC_OPEN_MAX); if (data_in) dup2(fd_stdin[0], STDIN_FILENO); if (max_wait != -1) { dup2(fd_stdout[1], STDERR_FILENO); dup2(fd_stdout[1], STDOUT_FILENO); for (i = 0; i < cc; i++) { if ((i != STDERR_FILENO) && (i != STDIN_FILENO) && (i != STDOUT_FILENO)) close(i); } } else { for (i = 0; i < cc; i++) { if (!data_in || (i != STDERR_FILENO)) close(i); } if ((cpid = fork()) < 0) exit(127); else if (cpid > 0) exit(0); } setpgid(0, 0); execv(script_path, script_argv); error("%s: execv(%s): %m", __func__, script_path); exit(127); } else if (cpid < 0) { if (data_in) { close(fd_stdin[0]); close(fd_stdin[1]); } if (max_wait != -1) { close(fd_stdout[0]); close(fd_stdout[1]); } error("%s: fork(): %m", __func__); } else if (max_wait != -1) { struct pollfd fds; time_t start_time = time(NULL); if (data_in) { close(fd_stdin[0]); send_size = strlen(data_in); while (send_size > send_offset) { i = write(fd_stdin[1], data_in + send_offset, send_size - send_offset); if (i == 0) { break; } else if (i < 0) { if (errno == EAGAIN) continue; error("%s: write(%s): %m", __func__, script_path); break; } else { send_offset += i; } } close(fd_stdin[1]); } resp_size = 1024; resp = xmalloc(resp_size); close(fd_stdout[1]); while (1) { fds.fd = fd_stdout[0]; fds.events = POLLIN | POLLHUP | POLLRDHUP; fds.revents = 0; if (max_wait <= 0) { new_wait = -1; } else { new_wait = (time(NULL) - start_time) * 1000 + max_wait; if (new_wait <= 0) break; } i = poll(&fds, 1, new_wait); if (i == 0) { error("%s: %s poll timeout", __func__, script_name); break; } else if (i < 0) { error("%s: %s poll:%m", __func__, script_name); break; } if ((fds.revents & POLLIN) == 0) break; i = read(fd_stdout[0], resp + resp_offset, resp_size - resp_offset); if (i == 0) { break; } else if (i < 0) { if (errno == EAGAIN) continue; error("%s: read(%s): %m", __func__, script_path); break; } else { resp_offset += i; if (resp_offset + 1024 >= resp_size) { resp_size *= 2; resp = xrealloc(resp, resp_size); } } } killpg(cpid, SIGKILL); waitpid(cpid, status, 0); close(fd_stdout[0]); } else { waitpid(cpid, status, 0); } return resp; }
void signalHandler(int signum){ if(cpid!=0){ killpg(cpid,SIGKILL); } }
VALUE rb_f_kill(int argc, VALUE *argv) { int negative = 0; int sig; int i; const char *s; rb_secure(2); if (argc < 2) rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)"); switch (TYPE(argv[0])) { case T_FIXNUM: sig = FIX2INT(argv[0]); break; case T_SYMBOL: s = rb_id2name(SYM2ID(argv[0])); if (!s) rb_raise(rb_eArgError, "bad signal"); goto str_signal; case T_STRING: s = RSTRING_PTR(argv[0]); if (s[0] == '-') { negative++; s++; } str_signal: if (strncmp("SIG", s, 3) == 0) s += 3; if((sig = signm2signo(s)) == 0) rb_raise(rb_eArgError, "unsupported name `SIG%s'", s); if (negative) sig = -sig; break; default: { VALUE str; str = rb_check_string_type(argv[0]); if (!NIL_P(str)) { s = RSTRING_PTR(str); goto str_signal; } rb_raise(rb_eArgError, "bad signal type %s", rb_obj_classname(argv[0])); } break; } if (sig < 0) { sig = -sig; for (i=1; i<argc; i++) { int pid = NUM2INT(argv[i]); #ifdef HAS_KILLPG if (killpg(pid, sig) < 0) #else if (kill(-pid, sig) < 0) #endif rb_sys_fail(0); } } else { for (i=1; i<argc; i++) { Check_Type(argv[i], T_FIXNUM); if (kill(FIX2INT(argv[i]), sig) < 0) rb_sys_fail(0); } } return INT2FIX(i-1); }
void cleanup(int signo) { /* Kill all Smews processes AND the simulator. No need to free any malloc... */ if(signo > 0 && signo <= 16) fprintf(stderr,"Signal received: %d (SIG%s)\n",signo,sigNames[signo-1]); killpg(0, SIGKILL); }
static int do_subprocess_kill(rktio_t *rktio, rktio_process_t *sp, int as_kill) { #if defined(RKTIO_SYSTEM_UNIX) # if defined(CENTRALIZED_SIGCHILD) { int status; if (sp->done) return 1; centralized_wait_suspend(); /* Don't allow group checking, because we don't want to wait on a group if we haven't already: */ if (centralized_get_child_status(sp->pid, 0, 0, &status)) { sp->status = status; sp->done = 1; centralized_wait_resume(); centralized_ended_child(); return 1; } } # else { System_Child *sc = (System_Child *)sp->handle; /* Don't pass sp->pid, because we don't want to wait on a group if we haven't already: */ check_child_done(rktio, 0); if (sc->done) return 1; } # define centralized_wait_resume() /* empty */ # endif while (1) { if (sp->is_group) { if (!killpg(sp->pid, as_kill ? SIGKILL : SIGINT)) { centralized_wait_resume(); return 1; } } else { if (!kill(sp->pid, as_kill ? SIGKILL : SIGINT)) { centralized_wait_resume(); return 1; } } if (errno != EINTR) break; /* Otherwise we were interrupted. Try `kill' again. */ } get_posix_error(); centralized_wait_resume(); return 0; #endif #if defined(RKTIO_SYSTEM_WINDOWS) if (as_kill || sp->is_group) { DWORD w; if (!sp->handle) return 1; if (!as_kill) { /* must be for a group; we don't care whether the original process is still running */ if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, sp->pid)) return 1; } else if (GetExitCodeProcess((HANDLE)sp->handle, &w)) { collect_process_time(rktio, w, sp); if (w != STILL_ACTIVE) return 1; if (TerminateProcess((HANDLE)sp->handle, 1)) return 1; } get_windows_error(); return 0; } else return 1; #endif }
int pipesexecute(char *cmdarr[MAXCMD][MAXOP],char *pipecmdarr[MAXCMD][MAXCMD][MAXOP],int *numofpipes,int ii) { //Execute piped commands int dupstdin = dup(0); int dupstdout = dup(1); int i,j=numofpipes[ii],k,pipes[2*numofpipes[ii]],pgid,comc = 0; for(i=0; j--; i+=2) { if((pipe(pipes+i))<0) //open the pipes { perror("pipe error"); return -1; } } j=0; k=0; while(j < (numofpipes[ii]+1)) { strcpy(infile,"\0"); strcpy(outfile,"\0"); k = 0; while(pipecmdarr[ii][j][k] != NULL) { if(strcmp(pipecmdarr[ii][j][k],"<") == 0) { if(fopen(pipecmdarr[ii][j][k+1],"r") == NULL) { printf("No such file exists\n"); return -1; } strcpy(infile,pipecmdarr[ii][j][k+1]); int kk; for(kk=k; kk<(MAXOP-2); kk++) { pipecmdarr[ii][j][kk] = pipecmdarr[ii][j][kk+2]; } break; } k++; } k=0; int outretval = 0; while(pipecmdarr[ii][j][k] != NULL) { if(strcmp(pipecmdarr[ii][j][k],">") == 0) { if(pipecmdarr[ii][j][k+1] != NULL) { strcpy(outfile,pipecmdarr[ii][j][k+1]); outretval = 1; int kk; for(kk=k; kk<(MAXOP-2); kk++) { pipecmdarr[ii][j][kk] = pipecmdarr[ii][j][kk+2]; } break; } else { printf("Unexpected error near > token\n"); strcpy(outfile,"\0"); return -1; } } if(strcmp(pipecmdarr[ii][j][k],">>") == 0) { if(pipecmdarr[ii][j][k+1] != NULL) { strcpy(outfile,pipecmdarr[ii][j][k+1]); outretval = 0; int kk; for(kk=k; kk<(MAXOP-2); kk++) { pipecmdarr[ii][j][kk] = pipecmdarr[ii][j][kk+2]; } break; } else { printf("Unexpected error near > token\n"); strcpy(outfile,"\0"); return -1; } } k++; } int pid = fork(),in,out; if(pid > 0) { //Parent if(comc == 0) pgid=pid; if(pid != 0) setpgid(pid,pgid); } else if(pid==0) { /*set the signal of child to default*/ signal (SIGINT, SIG_DFL); signal (SIGQUIT, SIG_DFL); signal (SIGTSTP, SIG_DFL); signal (SIGTTIN, SIG_DFL); signal (SIGTTOU, SIG_DFL); signal (SIGCHLD, SIG_DFL); if(strcmp(outfile,"\0") != 0 && pipecmdarr[ii][j+1][0] == NULL) { //if there is an outfile if(outretval == 1) { out=open(outfile,O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR); dup2(out,1); close(out); } else { if(fopen(outfile,"r") == NULL) { out=open(outfile,O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR); dup2(out,1); close(out); } else { out=open(outfile,O_WRONLY | O_APPEND, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR); dup2(out,1); close(out); } } } else if(pipecmdarr[ii][j+1][0] != NULL) { //if not the last command if((dup2(pipes[2*comc+1],1))<0) { perror("dup2 error"); } } else { if((dup2(dupstdout,1))<0) { perror("dup2 error"); } } if(strcmp(infile,"\0") != 0 && comc == 0) { //if there is an infile in=open(infile,O_RDONLY); dup2(in,0); close(in); } else if(comc!=0) { //if not the first command if((dup2(pipes[2*(comc-1)],0))<0) { perror("dup2 error"); } } else { if((dup2(dupstdin,0))<0) { perror("dup2 error"); } } //close all pipes in the children for(i=0; i<2*(numofpipes[ii]); i++) //close all pipes in the children close(pipes[i]); if((execvp(pipecmdarr[ii][j][0],pipecmdarr[ii][j]))<0) { perror("Cannot execute"); _exit(-1); } } else if(pid<0) { perror("Could not fork child"); return -1; } if(pipecmdarr[ii][j][0] != NULL) comc++; j++; } int status; for(i=0; i<2*(numofpipes[ii]); i++) { close(pipes[i]); //close all pipes in parent } tcsetpgrp(shell_terminal,pgid); //set the terminal control to child for(i=0; i<(numofpipes[ii]+1); i++) { waitpid(-pgid,&status,WUNTRACED); //Wait for all processes in the pipe if(WIFSTOPPED(status)) killpg(pgid,SIGSTOP); } tcsetpgrp(shell_terminal,shell_pgid); //return control to parent return 0; }
/* stop all children */ void stop_children(int mode) { int status, chld; int waited = 0; int x, curpid; gm_log( GM_LOG_TRACE, "stop_children(%d)\n", mode); /* ignore some signals for now */ signal(SIGTERM, SIG_IGN); signal(SIGINT, SIG_IGN); /* * send term signal to our children * children will finish the current job and exit */ killpg(0, SIGTERM); while(current_number_of_workers > 0) { gm_log( GM_LOG_TRACE, "send SIGTERM\n"); for(x=3; x < mod_gm_opt->max_worker+4; x++) { curpid = shm[x]; if(curpid < 0) { curpid = -curpid; } if( curpid != 0 ) { kill(curpid, SIGTERM); } } while((chld = waitpid(-1, &status, WNOHANG)) != -1 && chld > 0) { gm_log( GM_LOG_TRACE, "wait() %d exited with %d\n", chld, status); } sleep(1); waited++; if(waited > GM_CHILD_SHUTDOWN_TIMEOUT) { break; } count_current_worker(GM_DISABLED); if(current_number_of_workers == 0) return; gm_log( GM_LOG_TRACE, "still waiting (%d) %d children missing...\n", waited, current_number_of_workers); } if(mode == GM_WORKER_STOP) { killpg(0, SIGINT); count_current_worker(GM_DISABLED); if(current_number_of_workers == 0) return; gm_log( GM_LOG_TRACE, "sending SIGINT...\n"); for(x=3; x < mod_gm_opt->max_worker+4; x++) { curpid = shm[x]; if(curpid < 0) { curpid = -curpid; } if( curpid != 0 ) { kill(curpid, SIGINT); } } while((chld = waitpid(-1, &status, WNOHANG)) != -1 && chld > 0) { gm_log( GM_LOG_TRACE, "wait() %d exited with %d\n", chld, status); } /* kill them the hard way */ count_current_worker(GM_DISABLED); if(current_number_of_workers == 0) return; for(x=3; x < mod_gm_opt->max_worker+4; x++) { if( shm[x] != 0 ) { curpid = shm[x]; if(curpid < 0) { curpid = -curpid; } if( curpid != 0 ) { kill(curpid, SIGKILL); } } } /* count children a last time */ count_current_worker(GM_DISABLED); if(current_number_of_workers == 0) return; /* this will kill us too */ gm_log( GM_LOG_ERROR, "exiting by SIGKILL...\n"); killpg(0, SIGKILL); } /* restore signal handlers for a clean exit */ signal(SIGINT, clean_exit); signal(SIGTERM,clean_exit); }
static int _call_external_program(stepd_step_rec_t *job) { int status, rc, opt; pid_t cpid; int max_wait = 300; /* seconds */ int time_remaining; if ((job->state != SLURMSTEPD_STEP_RUNNING) || program_name == NULL || program_name[0] == '\0') return 0; debug("step_terminate_monitor: unkillable after %d sec, calling: %s", timeout, program_name); if (access(program_name, R_OK | X_OK) < 0) { debug("step_terminate_monitor not running %s: %m", program_name); return 0; } if ((cpid = fork()) < 0) { error("step_terminate_monitor executing %s: fork: %m", program_name); return -1; } if (cpid == 0) { /* child */ char *argv[2]; char buf[16]; /* container_g_add_pid needs to be called in the forked process part of the fork to avoid a race condition where if this process makes a file or detacts itself from a child before we add the pid to the container in the parent of the fork. */ if (container_g_add_pid(recorded_jobid, getpid(), getuid()) != SLURM_SUCCESS) error("container_g_add_pid(%u): %m", recorded_jobid); snprintf(buf, 16, "%u", recorded_jobid); setenv("SLURM_JOBID", buf, 1); setenv("SLURM_JOB_ID", buf, 1); snprintf(buf, 16, "%u", recorded_stepid); setenv("SLURM_STEPID", buf, 1); setenv("SLURM_STEP_ID", buf, 1); argv[0] = program_name; argv[1] = NULL; setpgid(0, 0); execv(program_name, argv); error("step_terminate_monitor execv(): %m"); exit(127); } opt = WNOHANG; time_remaining = max_wait; while (1) { rc = waitpid(cpid, &status, opt); if (rc < 0) { if (errno == EINTR) continue; /* waitpid may very well fail under normal conditions because the wait3() in mgr.c:_wait_for_any_task() may have reaped the return code. */ return 0; } else if (rc == 0) { sleep(1); if ((--time_remaining) == 0) { error("step_terminate_monitor: %s still running" " after %d seconds. Killing.", program_name, max_wait); killpg(cpid, SIGKILL); opt = 0; } } else { return status; } } /* NOTREACHED */ }
static int _run_nhc(uint64_t id, char *nodelist, bool step) { #ifdef HAVE_NATIVE_CRAY int argc = 5, status = 1, wait_rc; char *argv[argc]; pid_t cpid; DEF_TIMERS; START_TIMER; argv[0] = "/opt/cray/nodehealth/default/bin/xtcleanup_after"; if (step) argv[1] = "-a"; else argv[1] = "-r"; argv[2] = xstrdup_printf("%"PRIu64"", id); argv[3] = cray_nodelist2nids(NULL, nodelist); argv[4] = NULL; if (debug_flags & DEBUG_FLAG_SELECT_TYPE) info("Calling NHC for id %"PRIu64" on nodes %s(%s)", id, nodelist, argv[3]); if ((cpid = fork()) < 0) { error("_run_nhc fork error: %m"); goto fini; } if (cpid == 0) { #ifdef SETPGRP_TWO_ARGS setpgrp(0, 0); #else setpgrp(); #endif execvp(argv[0], argv); exit(127); } while (1) { wait_rc = waitpid(cpid, &status, 0); if (wait_rc < 0) { if (errno == EINTR) continue; error("_run_nhc waitpid error: %m"); break; } else if (wait_rc > 0) { killpg(cpid, SIGKILL); /* kill children too */ break; } } END_TIMER; if (status != 0) { error("_run_nhc %s %"PRIu64" exit status %u:%u took: %s", step ? "step" : "job", step ? id : id, WEXITSTATUS(status), WTERMSIG(status), TIME_STR); } else if (debug_flags & DEBUG_FLAG_SELECT_TYPE) info("_run_nhc %s %"PRIu64" completed took: %s", step ? "step" : "job", step ? id : id, TIME_STR); fini: xfree(argv[2]); xfree(argv[3]); return status; #else if (debug_flags & DEBUG_FLAG_SELECT_TYPE) info("simluating calling NHC for id %"PRIu64" on nodes %s", id, nodelist); /* simulate sleeping */ sleep(2); return 0; #endif }
node* execute(node* jobList, char* largs[], char* rargs[], char* input, char* in, char* out, int pipestatus, int back, int jc, int error){ int pidl; int pidr = 0; int pg; int status; int count = 0; int new_outno; int new_inno; int fd[2]; char* job; node* current; node* recentJob; //error checking block if (error < 0) { if (error == -1) { write(1, "Error: Invalid I/O Input\n", 26); return jobList; } if (error == -2) { write(1, "Error: Invalid Pipe Input\n", 27); return jobList; } if (error == -3) { write(1, "Error: Invalid Background Input\n", 33); return jobList; } if (error == -4) { write(1, "Error: Invalid fg or bg input\n", 31); return jobList; } } //fg if (jc == 1) { //find a stopped job recentJob = findStopped(jobList); if (recentJob == NULL) { recentJob = jobList; // get the top of the stack } //this means that there are 0 background jobs if (recentJob == NULL) { printf("Error: No background jobs\n"); } //send cont signal, give tc to the group else { if (killpg(recentJob->pgid, SIGCONT) < 0) perror("kill"); if (tcsetpgrp(STDIN_FILENO, recentJob->pgid) < 0) perror("tcsetpgrp fg"); //get the pid and pg pidl = recentJob->pid; pg = recentJob->pgid; pipestatus = recentJob->pipe; job = malloc(slen(recentJob->command) + 1); scopy(recentJob->command, job); //if pipe, get the other pid too if(pipestatus) { jobList = delete(jobList, recentJob->pid); recentJob = getg(jobList, pg); pidr = recentJob->pid; } //delete the job off the bg list jobList = delete(jobList, recentJob->pid); //print job on the shell printf("%s\n", job); //wait for both processes to finish waitpid(pidl, &status, WUNTRACED); waitpid(pidr, &status, WUNTRACED); // if foreground was stopped, place this job onto the list, notify it was stopped if (WIFSTOPPED(status)) { printf("\nStopped: %s\n", job); jobList = push(jobList, job, pidl, getpgid(pidl), pipestatus, 1); if (pipestatus) jobList = push(jobList, job, pidr, getpgid(pidl), pipestatus, 1); } //free job (i wish) free(job); //take back control of tc if (tcsetpgrp(STDIN_FILENO, getpgid(0)) < 0) perror("tcsetpgrp parent"); jobList = bgWait(jobList); } return jobList; } //bg if (jc == 2) { // find a stopped job recentJob = findStopped(jobList); //if there are no stopped jobs, move on if (recentJob == NULL) { printf("Error: No stopped background jobs\n"); } //otherwise, give signal to that job to continue else { if (killpg(recentJob->pgid, SIGCONT) < 0) perror("kill"); pg = recentJob->pgid; jobList = changeStopped(jobList, pg); printf("Running : %s\n", recentJob->command); } // poll for background processes jobList = bgWait(jobList); //return return jobList; } //set up pipe fd's if (pipestatus) { if (pipe(fd) < 0) perror("Error"); } // fork - twice if there's a pipe if ((pidl = fork()) < 0) { perror("Error"); } //left command child branch if(pidl == 0) { //set all signals to default signal(SIGTTOU, SIG_DFL); signal(SIGTTIN, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGTSTP, SIG_DFL); signal(SIGINT, SIG_DFL); // set pgid if (setpgid(getpid(), getpid()) < 0) perror("setpgid"); // give tc if not background (both in child and parent for rc) if (!back) { if (tcsetpgrp(STDIN_FILENO, getpgid(0)) < 0) perror("tcsetpgrp child"); } //close input + dup2 out to the pipe if (pipestatus) { if (close(fd[0]) < 0) perror("Error"); if(dup2(fd[1], 1) < 0) perror("Error"); } // set I/O redirections in child process - stdout if (out != NULL && (!pipestatus)) { new_outno = open(out, O_WRONLY | O_TRUNC | O_CREAT, 0644); //to do - error check if (dup2(new_outno, STDOUT_FILENO) < 0) { perror("Error"); exit(1); } } //stdin if (in != NULL) { new_inno = open(in, O_RDONLY); //to do - error check if (dup2(new_inno, STDIN_FILENO) < 0) { perror("Error"); exit(1); } } // exec if (execvp(largs[0], largs) < 0) { perror("Error"); exit(1); } } //PARENT else { // SECOND PROCESS BRANCH if (pipestatus) { if((pidr = fork()) < 0) { perror("Error"); } // second child branch else if(pidr == 0) { //set all signals to default signal(SIGTTOU, SIG_DFL); signal(SIGTTIN, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGTSTP, SIG_DFL); signal(SIGINT, SIG_DFL); // set group id if foreground if (setpgid(getpid(), pidl) < 0) perror("Error"); // give tc if not background (both in child and parent for rc) if (!back) { if (tcsetpgrp(STDIN_FILENO, getpgid(0)) < 0) perror("tcsetpgrp child"); } //close output + dup2 input from pipe if (close(fd[1]) < 0) perror("Error"); if (dup2(fd[0], 0) < 0) perror("Error"); // set I/O redirections in child process - stdout if (out != NULL) { new_outno = open(out, O_WRONLY | O_TRUNC | O_CREAT, 0644); //to do - error check if (dup2(new_outno, STDOUT_FILENO) < 0) { perror("Error"); exit(1); } } // exec if (execvp(rargs[0], rargs) < 0) { perror("Error"); exit(1); } } } //PARENT BRANCH: //close both pipes in the parent if (pipestatus) { if (close(fd[0]) < 0) perror("Error"); if (close(fd[1]) < 0) perror("Error"); } //set groups if (setpgid(pidl, pidl) < 0) perror("setpgid"); if (pipestatus) { if (setpgid(pidr, pidl) < 0) perror("setpgid"); } //if background, put job into the list if (back) { jobList = push(jobList, input, pidl, getpgid(pidl), pipestatus, 0); // also put the right side on the list if pipe if (pipestatus) jobList = push(jobList, input, pidr, getpgid(pidr), pipestatus, 0); } //for foreground if (!back) { //set tcpgrp for child/children if (tcsetpgrp(STDIN_FILENO, pidl) < 0) perror("tcsetpgrp child"); //wait for both child processes to finish if not bg waitpid(pidl, &status, WUNTRACED); waitpid(pidr, &status, WUNTRACED); // if foreground was stopped, place this job onto the list, notify it was stopped if (WIFSTOPPED(status)) { printf("\nStopped: %s\n", input); jobList = push(jobList, input, pidl, getpgid(pidl), pipestatus, 1); if (pipestatus) jobList = push(jobList, input, pidr, getpgid(pidl), pipestatus, 1); } //take back control of tc if (tcsetpgrp(STDIN_FILENO, getpgid(0)) < 0) perror("tcsetpgrp parent"); } // wait for background jobList = bgWait(jobList); return jobList; } //should never get here but to fend off warnings return jobList; }
void signalHandler() { if (!done) killpg(0,SIGHUP); done = 1; }
VALUE rb_f_kill(int argc, const VALUE *argv) { #ifndef HAVE_KILLPG #define killpg(pg, sig) kill(-(pg), (sig)) #endif int negative = 0; int sig; int i; VALUE str; const char *s; rb_secure(2); rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS); switch (TYPE(argv[0])) { case T_FIXNUM: sig = FIX2INT(argv[0]); break; case T_SYMBOL: str = rb_sym2str(argv[0]); goto str_signal; case T_STRING: str = argv[0]; str_signal: s = RSTRING_PTR(str); if (s[0] == '-') { negative++; s++; } if (strncmp(signame_prefix, s, sizeof(signame_prefix)) == 0) s += 3; if ((sig = signm2signo(s)) == 0) { long ofs = s - RSTRING_PTR(str); if (ofs) str = rb_str_subseq(str, ofs, RSTRING_LEN(str)-ofs); rb_raise(rb_eArgError, "unsupported name `SIG%"PRIsVALUE"'", str); } if (negative) sig = -sig; break; default: str = rb_check_string_type(argv[0]); if (!NIL_P(str)) { goto str_signal; } rb_raise(rb_eArgError, "bad signal type %s", rb_obj_classname(argv[0])); break; } if (argc <= 1) return INT2FIX(0); if (sig < 0) { sig = -sig; for (i=1; i<argc; i++) { if (killpg(NUM2PIDT(argv[i]), sig) < 0) rb_sys_fail(0); } } else { const rb_pid_t self = (GET_THREAD() == GET_VM()->main_thread) ? getpid() : -1; int wakeup = 0; for (i=1; i<argc; i++) { rb_pid_t pid = NUM2PIDT(argv[i]); if ((sig != 0) && (self != -1) && (pid == self)) { int t; /* * When target pid is self, many caller assume signal will be * delivered immediately and synchronously. */ switch (sig) { case SIGSEGV: #ifdef SIGBUS case SIGBUS: #endif #ifdef SIGKILL case SIGKILL: #endif #ifdef SIGSTOP case SIGSTOP: #endif ruby_kill(pid, sig); break; default: t = signal_ignored(sig); if (t) { if (t < 0 && kill(pid, sig)) rb_sys_fail(0); break; } signal_enque(sig); wakeup = 1; } } else if (kill(pid, sig) < 0) { rb_sys_fail(0); } } if (wakeup) { rb_threadptr_check_signal(GET_VM()->main_thread); } } rb_thread_execute_interrupts(rb_thread_current()); return INT2FIX(i-1); }
/* Run a script and return its stdout plus exit status */ static char *_run_script(char **script_argv, int *status) { int cc, i, new_wait, resp_size = 0, resp_offset = 0; pid_t cpid; char *resp = NULL; int pfd[2] = { -1, -1 }; if (access(capmc_path, R_OK | X_OK) < 0) { error("%s: Can not execute: %s", prog_name, capmc_path); *status = 127; resp = xstrdup("Slurm node_features/knl_cray configuration error"); return resp; } if (pipe(pfd) != 0) { error("%s: pipe(): %s", prog_name, slurm_strerror(slurm_get_errno())); *status = 127; resp = xstrdup("System error"); return resp; } if ((cpid = fork()) == 0) { cc = sysconf(_SC_OPEN_MAX); dup2(pfd[1], STDERR_FILENO); dup2(pfd[1], STDOUT_FILENO); for (i = 0; i < cc; i++) { if ((i != STDERR_FILENO) && (i != STDOUT_FILENO)) close(i); } setpgid(0, 0); execv(capmc_path, script_argv); error("%s: execv(): %s", prog_name, slurm_strerror(slurm_get_errno())); exit(127); } else if (cpid < 0) { close(pfd[0]); close(pfd[1]); error("%s: fork(): %s", prog_name, slurm_strerror(slurm_get_errno())); *status = 127; resp = xstrdup("System error"); return resp; } else { struct pollfd fds; struct timeval tstart; resp_size = 1024; resp = xmalloc(resp_size); close(pfd[1]); gettimeofday(&tstart, NULL); while (1) { fds.fd = pfd[0]; fds.events = POLLIN | POLLHUP | POLLRDHUP; fds.revents = 0; new_wait = capmc_timeout - _tot_wait(&tstart); if (new_wait <= 0) { error("%s: poll() timeout @ %d msec", prog_name, capmc_timeout); break; } new_wait = MIN(new_wait, MAX_POLL_WAIT); i = poll(&fds, 1, new_wait); if (i == 0) { continue; } else if (i < 0) { error("%s: poll(): %s", prog_name, slurm_strerror(slurm_get_errno())); break; } if ((fds.revents & POLLIN) == 0) break; i = read(pfd[0], resp + resp_offset, resp_size - resp_offset); if (i == 0) { break; } else if (i < 0) { if (errno == EAGAIN) continue; error("%s: read(): %s", prog_name, slurm_strerror(slurm_get_errno())); break; } else { resp_offset += i; if (resp_offset + 1024 >= resp_size) { resp_size *= 2; resp = xrealloc(resp, resp_size); } } } killpg(cpid, SIGTERM); usleep(10000); killpg(cpid, SIGKILL); waitpid(cpid, status, 0); close(pfd[0]); } return resp; }
/** * Clean up and then exit with the associated return code */ void cleanup(parallel_wrapper *par_wrapper, int return_code) { int i, j; /* Try to lock the keep-alive mutex */ pthread_mutex_trylock(&keep_alive_mutex); if (par_wrapper -> this_machine -> rank == MASTER && par_wrapper -> machines != (machine **)NULL) { /* Send the term signal (don't send to self) */ for (i = 1; i < par_wrapper -> num_procs; i++) { if (par_wrapper -> machines[i] == (machine *)NULL) { continue; } for (j = 0; j < 10; j++) { term(par_wrapper -> command_socket, return_code, par_wrapper -> machines[i] -> ip_addr, par_wrapper -> machines[i] -> port); usleep(100000); /* Sleep 1/10th second */ } } } /* If we spawned subgroups, attempt to kill them all */ if (par_wrapper -> pgid > 0 && par_wrapper -> child_pid > 0) { int RC = killpg(par_wrapper -> child_pid, SIGTERM); if (RC == EPERM) { print(PRNT_WARN, "Unable to kill child pid %d - permission denied\n"); } else if (RC == 0) { debug(PRNT_INFO, "Sent SIGTERM to child group %d\n", par_wrapper -> child_pid); } } /* Lock the parallel_wrapper structure */ pthread_mutex_trylock(&par_wrapper -> mutex); /* Clean up the scratch directory */ cleanup_scratch(par_wrapper -> scratch_dir); /* Unlink all softlinks */ if (is_valid_sll(par_wrapper -> symlinks)) { struct sll_element *element = par_wrapper -> symlinks -> head -> next; while (element != (struct sll_element *)NULL) { char *filename = (char *)element -> ptr; if (filename != (char *)NULL) { if (unlink(filename) != 0) { print(PRNT_WARN, "Unable to unlink file %s\n", filename); } } element = element -> next; } } /* No need to unlock - we are exitting */ exit(return_code); }
int main() { int child_pid, child_pgid; if ((child_pid = fork()) == 0) { /* child here */ struct sigaction act; act.sa_handler=myhandler; act.sa_flags=0; sigemptyset(&act.sa_mask); sigaction(SIGTOTEST, &act, 0); /* change child's process group id */ /* * XXX: POSIX 1003.1-2001 added setpgrp(2) to BASE, but * unfortunately BSD has had their own implementations for * ages for compatibility reasons. */ #if __FreeBSD__ || __NetBSD__ || __OpenBSD__ setpgrp(0, 0); #else setpgrp(); #endif sigpause(SIGABRT); return 0; } else { /* parent here */ int i; sigignore(SIGTOTEST); sleep(1); if ((child_pgid = getpgid(child_pid)) == -1) { printf("Could not get pgid of child\n"); return PTS_UNRESOLVED; } if (killpg(child_pgid, SIGTOTEST) != 0) { printf("Could not raise signal being tested\n"); return PTS_UNRESOLVED; } if (wait(&i) == -1) { perror("Error waiting for child to exit\n"); return PTS_UNRESOLVED; } if (WEXITSTATUS(i)) { printf("Child exited normally\n"); printf("Test PASSED\n"); return PTS_PASS; } else { printf("Child did not exit normally.\n"); printf("Test FAILED\n"); return PTS_FAIL; } } printf("Should have exited from parent\n"); printf("Test FAILED\n"); return PTS_FAIL; }
void job_continue(job_t *j, bool cont) { /* Put job first in the job list */ job_promote(j); job_set_flag(j, JOB_NOTIFIED, 0); CHECK_BLOCK(); debug(4, L"Continue job %d, gid %d (%ls), %ls, %ls", j->job_id, j->pgid, j->command_wcstr(), job_is_completed(j)?L"COMPLETED":L"UNCOMPLETED", is_interactive?L"INTERACTIVE":L"NON-INTERACTIVE"); if (!job_is_completed(j)) { if (job_get_flag(j, JOB_TERMINAL) && job_get_flag(j, JOB_FOREGROUND)) { /* Put the job into the foreground. Hack: ensure that stdin is marked as blocking first (#176). */ make_fd_blocking(STDIN_FILENO); signal_block(); bool ok = terminal_give_to_job(j, cont); signal_unblock(); if (!ok) return; } /* Send the job a continue signal, if necessary. */ if (cont) { process_t *p; for (p=j->first_process; p; p=p->next) p->stopped=0; if (job_get_flag(j, JOB_CONTROL)) { if (killpg(j->pgid, SIGCONT)) { wperror(L"killpg (SIGCONT)"); return; } } else { for (p=j->first_process; p; p=p->next) { if (kill(p->pid, SIGCONT) < 0) { wperror(L"kill (SIGCONT)"); return; } } } } if (job_get_flag(j, JOB_FOREGROUND)) { /* Look for finished processes first, to avoid select() if it's already done. */ process_mark_finished_children(false); /* Wait for job to report. */ while (! reader_exit_forced() && ! job_is_stopped(j) && ! job_is_completed(j)) { // debug( 1, L"select_try()" ); switch (select_try(j)) { case 1: { read_try(j); process_mark_finished_children(false); break; } case 0: { /* No FDs are ready. Look for finished processes. */ process_mark_finished_children(false); break; } case -1: { /* If there is no funky IO magic, we can use waitpid instead of handling child deaths through signals. This gives a rather large speed boost (A factor 3 startup time improvement on my 300 MHz machine) on short-lived jobs. This will return early if we get a signal, like SIGHUP. */ process_mark_finished_children(true); break; } } } } } if (job_get_flag(j, JOB_FOREGROUND)) { if (job_is_completed(j)) { // It's possible that the job will produce output and exit before we've even read from it. // We'll eventually read the output, but it may be after we've executed subsequent calls // This is why my prompt colors kept getting screwed up - the builtin echo calls // were sometimes having their output combined with the set_color calls in the wrong order! read_try(j); process_t *p = j->first_process; while (p->next) p = p->next; if (WIFEXITED(p->status) || WIFSIGNALED(p->status)) { /* Mark process status only if we are in the foreground and the last process in a pipe, and it is not a short circuited builtin */ if (p->pid) { int status = proc_format_status(p->status); //wprintf(L"setting status %d for %ls\n", job_get_flag( j, JOB_NEGATE )?!status:status, j->command); proc_set_last_status(job_get_flag(j, JOB_NEGATE)?!status:status); } } } /* Put the shell back in the foreground. */ if (job_get_flag(j, JOB_TERMINAL) && job_get_flag(j, JOB_FOREGROUND)) { int ok; signal_block(); ok = terminal_return_from_job(j); signal_unblock(); if (!ok) return; } } }
int main(int argc, char *argv[]) { log_options_t logopt = LOG_OPTS_STDERR_ONLY; job_desc_msg_t desc; resource_allocation_response_msg_t *alloc; time_t before, after; allocation_msg_thread_t *msg_thr; char **env = NULL, *cluster_name; int status = 0; int retries = 0; pid_t pid = getpid(); pid_t tpgid = 0; pid_t rc_pid = 0; int i, rc = 0; static char *msg = "Slurm job queue full, sleeping and retrying."; slurm_allocation_callbacks_t callbacks; slurm_conf_init(NULL); log_init(xbasename(argv[0]), logopt, 0, NULL); _set_exit_code(); if (spank_init_allocator() < 0) { error("Failed to initialize plugin stack"); exit(error_exit); } /* Be sure to call spank_fini when salloc exits */ if (atexit((void (*) (void)) spank_fini) < 0) error("Failed to register atexit handler for plugins: %m"); if (initialize_and_process_args(argc, argv) < 0) { error("salloc parameter parsing"); exit(error_exit); } /* reinit log with new verbosity (if changed by command line) */ if (opt.verbose || opt.quiet) { logopt.stderr_level += opt.verbose; logopt.stderr_level -= opt.quiet; logopt.prefix_level = 1; log_alter(logopt, 0, NULL); } if (spank_init_post_opt() < 0) { error("Plugin stack post-option processing failed"); exit(error_exit); } _set_spank_env(); _set_submit_dir_env(); if (opt.cwd && chdir(opt.cwd)) { error("chdir(%s): %m", opt.cwd); exit(error_exit); } if (opt.get_user_env_time >= 0) { bool no_env_cache = false; char *sched_params; char *user = uid_to_string(opt.uid); if (xstrcmp(user, "nobody") == 0) { error("Invalid user id %u: %m", (uint32_t)opt.uid); exit(error_exit); } sched_params = slurm_get_sched_params(); no_env_cache = (sched_params && strstr(sched_params, "no_env_cache")); xfree(sched_params); env = env_array_user_default(user, opt.get_user_env_time, opt.get_user_env_mode, no_env_cache); xfree(user); if (env == NULL) exit(error_exit); /* error already logged */ _set_rlimits(env); } /* * Job control for interactive salloc sessions: only if ... * * a) input is from a terminal (stdin has valid termios attributes), * b) controlling terminal exists (non-negative tpgid), * c) salloc is not run in allocation-only (--no-shell) mode, * NOTE: d and e below are configuration dependent * d) salloc runs in its own process group (true in interactive * shells that support job control), * e) salloc has been configured at compile-time to support background * execution and is not currently in the background process group. */ if (tcgetattr(STDIN_FILENO, &saved_tty_attributes) < 0) { /* * Test existence of controlling terminal (tpgid > 0) * after first making sure stdin is not redirected. */ } else if ((tpgid = tcgetpgrp(STDIN_FILENO)) < 0) { #ifdef HAVE_ALPS_CRAY verbose("no controlling terminal"); #else if (!opt.no_shell) { error("no controlling terminal: please set --no-shell"); exit(error_exit); } #endif #ifdef SALLOC_RUN_FOREGROUND } else if ((!opt.no_shell) && (pid == getpgrp())) { if (tpgid == pid) is_interactive = true; while (tcgetpgrp(STDIN_FILENO) != pid) { if (!is_interactive) { error("Waiting for program to be placed in " "the foreground"); is_interactive = true; } killpg(pid, SIGTTIN); } } #else } else if ((!opt.no_shell) && (getpgrp() == tcgetpgrp(STDIN_FILENO))) {
void App::Login() { struct passwd *pw; pid_t pid; pw = LoginPanel->GetInput()->GetPasswdStruct(); if(pw == 0) return; // Create new process pid = fork(); if(pid == 0) { // Login process starts here SwitchUser Su(pw, &cfg, DisplayName); string session = LoginPanel->getSession(); string loginCommand = cfg.getOption("login_cmd"); replaceVariables(loginCommand, SESSION_VAR, session); replaceVariables(loginCommand, THEME_VAR, themeName); string sessStart = cfg.getOption("sessionstart_cmd"); if (sessStart != "") { replaceVariables(sessStart, USER_VAR, pw->pw_name); system(sessStart.c_str()); } Su.Login(loginCommand.c_str()); exit(OK_EXIT); } #ifndef XNEST_DEBUG CloseLog(); #endif // Wait until user is logging out (login process terminates) pid_t wpid = -1; int status; while (wpid != pid) { wpid = wait(&status); } if (WIFEXITED(status) && WEXITSTATUS(status)) { LoginPanel->Message("Failed to execute login command"); } else { string sessStop = cfg.getOption("sessionstop_cmd"); if (sessStop != "") { replaceVariables(sessStop, USER_VAR, pw->pw_name); system(sessStop.c_str()); } } // Close all clients KillAllClients(False); KillAllClients(True); // Send HUP signal to clientgroup killpg(pid, SIGHUP); // Send TERM signal to clientgroup, if error send KILL if(killpg(pid, SIGTERM)) killpg(pid, SIGKILL); HideCursor(); #ifndef XNEST_DEBUG // Re-activate log file OpenLog(); #endif }
/* Execute a script, wait for termination and return its stdout. * script_type IN - Type of program being run (e.g. "StartStageIn") * script_path IN - Fully qualified pathname of the program to execute * script_args IN - Arguments to the script * max_wait IN - Maximum time to wait in milliseconds, * -1 for no limit (asynchronous) * status OUT - Job exit code * Return stdout+stderr of spawned program, value must be xfreed. */ extern char *bb_run_script(char *script_type, char *script_path, char **script_argv, int max_wait, int *status) { int i, new_wait, resp_size = 0, resp_offset = 0; pid_t cpid; char *resp = NULL; int pfd[2] = { -1, -1 }; if ((script_path == NULL) || (script_path[0] == '\0')) { error("%s: no script specified", __func__); *status = 127; resp = xstrdup("Slurm burst buffer configuration error"); return resp; } if (script_path[0] != '/') { error("%s: %s is not fully qualified pathname (%s)", __func__, script_type, script_path); *status = 127; resp = xstrdup("Slurm burst buffer configuration error"); return resp; } if (access(script_path, R_OK | X_OK) < 0) { error("%s: %s can not be executed (%s) %m", __func__, script_type, script_path); *status = 127; resp = xstrdup("Slurm burst buffer configuration error"); return resp; } if (max_wait != -1) { if (pipe(pfd) != 0) { error("%s: pipe(): %m", __func__); *status = 127; resp = xstrdup("System error"); return resp; } } slurm_mutex_lock(&proc_count_mutex); child_proc_count++; slurm_mutex_unlock(&proc_count_mutex); if ((cpid = fork()) == 0) { int cc; cc = sysconf(_SC_OPEN_MAX); if (max_wait != -1) { dup2(pfd[1], STDERR_FILENO); dup2(pfd[1], STDOUT_FILENO); for (i = 0; i < cc; i++) { if ((i != STDERR_FILENO) && (i != STDOUT_FILENO)) close(i); } } else { for (i = 0; i < cc; i++) close(i); if ((cpid = fork()) < 0) exit(127); else if (cpid > 0) exit(0); } setpgid(0, 0); execv(script_path, script_argv); error("%s: execv(%s): %m", __func__, script_path); exit(127); } else if (cpid < 0) { if (max_wait != -1) { close(pfd[0]); close(pfd[1]); } error("%s: fork(): %m", __func__); slurm_mutex_lock(&proc_count_mutex); child_proc_count--; slurm_mutex_unlock(&proc_count_mutex); } else if (max_wait != -1) { struct pollfd fds; struct timeval tstart; resp_size = 1024; resp = xmalloc(resp_size); close(pfd[1]); gettimeofday(&tstart, NULL); while (1) { if (bb_plugin_shutdown) { error("%s: killing %s operation on shutdown", __func__, script_type); break; } fds.fd = pfd[0]; fds.events = POLLIN | POLLHUP | POLLRDHUP; fds.revents = 0; if (max_wait <= 0) { new_wait = MAX_POLL_WAIT; } else { new_wait = max_wait - _tot_wait(&tstart); if (new_wait <= 0) { error("%s: %s poll timeout @ %d msec", __func__, script_type, max_wait); break; } new_wait = MIN(new_wait, MAX_POLL_WAIT); } i = poll(&fds, 1, new_wait); if (i == 0) { continue; } else if (i < 0) { error("%s: %s poll:%m", __func__, script_type); break; } if ((fds.revents & POLLIN) == 0) break; i = read(pfd[0], resp + resp_offset, resp_size - resp_offset); if (i == 0) { break; } else if (i < 0) { if (errno == EAGAIN) continue; error("%s: read(%s): %m", __func__, script_path); break; } else { resp_offset += i; if (resp_offset + 1024 >= resp_size) { resp_size *= 2; resp = xrealloc(resp, resp_size); } } } killpg(cpid, SIGTERM); usleep(10000); killpg(cpid, SIGKILL); waitpid(cpid, status, 0); close(pfd[0]); slurm_mutex_lock(&proc_count_mutex); child_proc_count--; slurm_mutex_unlock(&proc_count_mutex); } else { waitpid(cpid, status, 0); } return resp; }
void doit(struct sockaddr *fromp) { extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */ struct passwd *pwd; u_short port; fd_set ready, readfrom; int cc, fd, nfd, pv[2], pid, s; int one = 1; const char *cp, *errorstr; char sig, buf[BUFSIZ]; char *cmdbuf, luser[16], ruser[16]; char rhost[2 * MAXHOSTNAMELEN + 1]; char numericname[INET6_ADDRSTRLEN]; int af, srcport; int maxcmdlen; login_cap_t *lc; maxcmdlen = (int)sysconf(_SC_ARG_MAX); if (maxcmdlen <= 0 || (cmdbuf = malloc(maxcmdlen)) == NULL) exit(1); (void) signal(SIGINT, SIG_DFL); (void) signal(SIGQUIT, SIG_DFL); (void) signal(SIGTERM, SIG_DFL); af = fromp->sa_family; srcport = ntohs(*((in_port_t *)&fromp->sa_data)); if (af == AF_INET) { inet_ntop(af, &((struct sockaddr_in *)fromp)->sin_addr, numericname, sizeof numericname); } else if (af == AF_INET6) { inet_ntop(af, &((struct sockaddr_in6 *)fromp)->sin6_addr, numericname, sizeof numericname); } else { syslog(LOG_ERR, "malformed \"from\" address (af %d)", af); exit(1); } #ifdef IP_OPTIONS if (af == AF_INET) { u_char optbuf[BUFSIZ/3]; socklen_t optsize = sizeof(optbuf), ipproto, i; struct protoent *ip; if ((ip = getprotobyname("ip")) != NULL) ipproto = ip->p_proto; else ipproto = IPPROTO_IP; if (!getsockopt(0, ipproto, IP_OPTIONS, optbuf, &optsize) && optsize != 0) { for (i = 0; i < optsize; ) { u_char c = optbuf[i]; if (c == IPOPT_LSRR || c == IPOPT_SSRR) { syslog(LOG_NOTICE, "connection refused from %s with IP option %s", numericname, c == IPOPT_LSRR ? "LSRR" : "SSRR"); exit(1); } if (c == IPOPT_EOL) break; i += (c == IPOPT_NOP) ? 1 : optbuf[i+1]; } } } #endif if (srcport >= IPPORT_RESERVED || srcport < IPPORT_RESERVED/2) { syslog(LOG_NOTICE|LOG_AUTH, "connection from %s on illegal port %u", numericname, srcport); exit(1); } (void) alarm(60); port = 0; s = 0; /* not set or used if port == 0 */ for (;;) { char c; if ((cc = read(STDIN_FILENO, &c, 1)) != 1) { if (cc < 0) syslog(LOG_NOTICE, "read: %m"); shutdown(0, SHUT_RDWR); exit(1); } if (c == 0) break; port = port * 10 + c - '0'; } (void) alarm(0); if (port != 0) { int lport = IPPORT_RESERVED - 1; s = rresvport_af(&lport, af); if (s < 0) { syslog(LOG_ERR, "can't get stderr port: %m"); exit(1); } if (port >= IPPORT_RESERVED || port < IPPORT_RESERVED/2) { syslog(LOG_NOTICE|LOG_AUTH, "2nd socket from %s on unreserved port %u", numericname, port); exit(1); } *((in_port_t *)&fromp->sa_data) = htons(port); if (connect(s, fromp, fromp->sa_len) < 0) { syslog(LOG_INFO, "connect second port %d: %m", port); exit(1); } } errorstr = NULL; realhostname_sa(rhost, sizeof(rhost) - 1, fromp, fromp->sa_len); rhost[sizeof(rhost) - 1] = '\0'; /* XXX truncation! */ (void) alarm(60); getstr(ruser, sizeof(ruser), "ruser"); getstr(luser, sizeof(luser), "luser"); getstr(cmdbuf, maxcmdlen, "command"); (void) alarm(0); pam_err = pam_start("rsh", luser, &pamc, &pamh); if (pam_err != PAM_SUCCESS) { syslog(LOG_ERR|LOG_AUTH, "pam_start(): %s", pam_strerror(pamh, pam_err)); rshd_errx(1, "Login incorrect."); } if ((pam_err = pam_set_item(pamh, PAM_RUSER, ruser)) != PAM_SUCCESS || (pam_err = pam_set_item(pamh, PAM_RHOST, rhost)) != PAM_SUCCESS) { syslog(LOG_ERR|LOG_AUTH, "pam_set_item(): %s", pam_strerror(pamh, pam_err)); rshd_errx(1, "Login incorrect."); } pam_err = pam_authenticate(pamh, 0); if (pam_err == PAM_SUCCESS) { if ((pam_err = pam_get_user(pamh, &cp, NULL)) == PAM_SUCCESS) { strncpy(luser, cp, sizeof(luser)); luser[sizeof(luser) - 1] = '\0'; /* XXX truncation! */ } pam_err = pam_acct_mgmt(pamh, 0); } if (pam_err != PAM_SUCCESS) { syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: permission denied (%s). cmd='%.80s'", ruser, rhost, luser, pam_strerror(pamh, pam_err), cmdbuf); rshd_errx(1, "Login incorrect."); } setpwent(); pwd = getpwnam(luser); if (pwd == NULL) { syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: unknown login. cmd='%.80s'", ruser, rhost, luser, cmdbuf); if (errorstr == NULL) errorstr = "Login incorrect."; rshd_errx(1, errorstr, rhost); } lc = login_getpwclass(pwd); if (pwd->pw_uid) auth_checknologin(lc); if (chdir(pwd->pw_dir) < 0) { if (chdir("/") < 0 || login_getcapbool(lc, "requirehome", !!pwd->pw_uid)) { syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: no home directory. cmd='%.80s'", ruser, rhost, luser, cmdbuf); rshd_errx(0, "No remote home directory."); } pwd->pw_dir = slash; } if (lc != NULL && fromp->sa_family == AF_INET) { /*XXX*/ char remote_ip[MAXHOSTNAMELEN]; strncpy(remote_ip, numericname, sizeof(remote_ip) - 1); remote_ip[sizeof(remote_ip) - 1] = 0; /* XXX truncation! */ if (!auth_hostok(lc, rhost, remote_ip)) { syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: permission denied (%s). cmd='%.80s'", ruser, rhost, luser, __rcmd_errstr, cmdbuf); rshd_errx(1, "Login incorrect."); } if (!auth_timeok(lc, time(NULL))) rshd_errx(1, "Logins not available right now"); } /* * PAM modules might add supplementary groups in * pam_setcred(), so initialize them first. * But we need to open the session as root. */ if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETGROUP) != 0) { syslog(LOG_ERR, "setusercontext: %m"); exit(1); } if ((pam_err = pam_open_session(pamh, 0)) != PAM_SUCCESS) { syslog(LOG_ERR, "pam_open_session: %s", pam_strerror(pamh, pam_err)); } else if ((pam_err = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) { syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, pam_err)); } (void) write(STDERR_FILENO, "\0", 1); sent_null = 1; if (port) { if (pipe(pv) < 0) rshd_errx(1, "Can't make pipe."); pid = fork(); if (pid == -1) rshd_errx(1, "Can't fork; try again."); if (pid) { (void) close(0); (void) close(1); (void) close(2); (void) close(pv[1]); FD_ZERO(&readfrom); FD_SET(s, &readfrom); FD_SET(pv[0], &readfrom); if (pv[0] > s) nfd = pv[0]; else nfd = s; ioctl(pv[0], FIONBIO, (char *)&one); /* should set s nbio! */ nfd++; do { ready = readfrom; if (select(nfd, &ready, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0) break; if (FD_ISSET(s, &ready)) { int ret; ret = read(s, &sig, 1); if (ret <= 0) FD_CLR(s, &readfrom); else killpg(pid, sig); } if (FD_ISSET(pv[0], &ready)) { errno = 0; cc = read(pv[0], buf, sizeof(buf)); if (cc <= 0) { shutdown(s, SHUT_RDWR); FD_CLR(pv[0], &readfrom); } else { (void)write(s, buf, cc); } } } while (FD_ISSET(s, &readfrom) || FD_ISSET(pv[0], &readfrom)); PAM_END; exit(0); } (void) close(s); (void) close(pv[0]); dup2(pv[1], 2); close(pv[1]); } else { pid = fork(); if (pid == -1) rshd_errx(1, "Can't fork; try again."); if (pid) { /* Parent. */ while (wait(NULL) > 0 || errno == EINTR) /* nothing */ ; PAM_END; exit(0); } } for (fd = getdtablesize(); fd > 2; fd--) (void) close(fd); if (setsid() == -1) syslog(LOG_ERR, "setsid() failed: %m"); if (setlogin(pwd->pw_name) < 0) syslog(LOG_ERR, "setlogin() failed: %m"); if (*pwd->pw_shell == '\0') pwd->pw_shell = bshell; (void) pam_setenv(pamh, "HOME", pwd->pw_dir, 1); (void) pam_setenv(pamh, "SHELL", pwd->pw_shell, 1); (void) pam_setenv(pamh, "USER", pwd->pw_name, 1); (void) pam_setenv(pamh, "PATH", _PATH_DEFPATH, 1); environ = pam_getenvlist(pamh); (void) pam_end(pamh, pam_err); cp = strrchr(pwd->pw_shell, '/'); if (cp) cp++; else cp = pwd->pw_shell; if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETALL & ~LOGIN_SETGROUP) < 0) { syslog(LOG_ERR, "setusercontext(): %m"); exit(1); } login_close(lc); endpwent(); if (log_success || pwd->pw_uid == 0) { syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'", ruser, rhost, luser, cmdbuf); } execl(pwd->pw_shell, cp, "-c", cmdbuf, (char *)NULL); err(1, "%s", pwd->pw_shell); exit(1); }
/* * 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; 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(%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 */ }
void runSuccess() { killpg(anypid(), anyint()); }