static int spawn_worker(char *cmd) { /* params struct for both workers */ struct worker_params params; /* children's pids */ pid_t c1, c2; int status, ret = 0; trim(cmd); params.cmd = cmd; if(open_pipe(params.pipe) == -1) { (void) fprintf(stderr, "%s: Could not create pipe\n", pgname); return -1; } /* We flush all our standard fd's so we'll have them empty in the workers */ fflush(stdin); fflush(stdout); fflush(stderr); /* Fork execute worker */ if((c1 = fork_function(execute, ¶ms)) == -1) { (void) fprintf(stderr, "%s: Could not spawn execute worker\n", pgname); close_pipe(params.pipe, channel_all); return -1; } /* Fork format worker */ if((c2 = fork_function(format, ¶ms)) == -1) { (void) fprintf(stderr, "%s: Could not spawn format worker\n", pgname); /* Wait for child 1 */ if(wait_for_child(c1) == -1) { (void) fprintf(stderr, "%s: Error waiting for execute worker to finish\n", pgname); } close_pipe(params.pipe, channel_all); return -1; } /* We need to close the pipe in parent, so that the format worker will quit working when execute's output has finished */ close_pipe(params.pipe, channel_all); if((status = wait_for_child(c1)) != 0) { (void) fprintf(stderr, "%s: Execute worker returned %d\n", pgname, status); /* not neccessarily an error. If there was a typo in cmd don't quit the whole programm */ // ret = -1; } if((status = wait_for_child(c2)) != 0) { (void) fprintf(stderr, "%s: Format worker returned %d\n", pgname, status); // ret = -1; } return ret; }
int main(int argc, char *argv[]) { pid_t child = fork(); if (child < 0) { perror("fork"); return EXIT_FAILURE; } if (child == 0) { // Child printf("child: attempting to dereference a NULL pointer...\n"); int *p = (int *) NULL; // Geronimo! *p = 209; } else { // Parent // Reap child wait_for_child(child); } return EXIT_SUCCESS; }
int perform_ping_measurement(std::istream& in) { std::string line; while (!in.eof()) { std::getline(in, line); if (line == "") { continue; } char* command[] = { (char*)"ping", (char*)"-c", (char*)"2", (char*)line.c_str(), NULL }; start_process("ping", command, "/dev/null", line); } //std::cout << "Started all processes. Now waiting for them to finish ..." << std::endl; // wait for all child processes to finsih (finished_processes is modified in // signal handler) while (started_counter != finished_counter) { wait_for_child(0); } for (std::map<std::string, int>::const_iterator i = finished_processes.begin(); i != finished_processes.end(); ++i) { if (i->second != 0) { std::cout << i->first << std::endl; } } return 0; }
int exec_command (const std::vector<std::string>& command) { HANDLE child_handle = spawn_command(command, NULL, NULL, NULL); int exit_code = wait_for_child(child_handle); CloseHandle(child_handle); return exit_code; }
void perfmon_init(void) { size_t i; long nr; if (cpu_type == CPU_TIMER_INT) return; if (!no_xen) { xen_ctx = xmalloc(sizeof(struct child)); xen_ctx->pid = getpid(); xen_ctx->up_pipe[0] = -1; xen_ctx->up_pipe[1] = -1; xen_ctx->sigusr1 = 0; xen_ctx->sigusr2 = 0; xen_ctx->sigterm = 0; create_context(xen_ctx); write_pmu(xen_ctx); load_context(xen_ctx); return; } nr = sysconf(_SC_NPROCESSORS_ONLN); if (nr == -1) { fprintf(stderr, "Couldn't determine number of CPUs.\n"); exit(EXIT_FAILURE); } nr_cpus = nr; children = xmalloc(sizeof(struct child) * nr_cpus); bzero(children, sizeof(struct child) * nr_cpus); for (i = 0; i < nr_cpus; ++i) { int ret; if (pipe(children[i].up_pipe)) { perror("Couldn't create child pipe"); exit(EXIT_FAILURE); } ret = fork(); if (ret == -1) { perror("Couldn't fork perfmon child"); exit(EXIT_FAILURE); } else if (ret == 0) { close(children[i].up_pipe[0]); run_child(i); } else { children[i].pid = ret; close(children[i].up_pipe[1]); printf("Waiting on CPU%d\n", (int)i); wait_for_child(&children[i]); } } }
/* Tests that fork clears EBB state */ int fork_cleanup(void) { pid_t pid; event_init_named(&event, 0x1001e, "cycles"); event_leader_ebb_init(&event); FAIL_IF(event_open(&event)); ebb_enable_pmc_counting(1); setup_ebb_handler(standard_ebb_callee); ebb_global_enable(); FAIL_IF(ebb_event_enable(&event)); mtspr(SPRN_MMCR0, MMCR0_FC); mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); /* Don't need to actually take any EBBs */ pid = fork(); if (pid == 0) exit(child()); /* Child does the actual testing */ FAIL_IF(wait_for_child(pid)); /* After fork */ event_close(&event); return 0; }
EXPORTED int command_pclose(struct command **cmdp) { struct command *cmd = (cmdp ? *cmdp : NULL); int r; if (!cmd) return 0; if (cmd->stdin_prot) { prot_flush(cmd->stdin_prot); close(cmd->stdin_prot->fd); prot_free(cmd->stdin_prot); } if (cmd->stdout_prot) { close(cmd->stdout_prot->fd); prot_free(cmd->stdout_prot); } r = wait_for_child(cmd->argv0, cmd->pid); free(cmd->argv0); free(cmd); *cmdp = NULL; return r; }
void check_children_count_and_wait_if_too_many() { if (children_count > MAX_CHILDREN) { fprintf(stderr, "max number of children reached, waiting for child exit...\n"); wait_for_child(); fprintf(stderr, "now children_count=%d, continuing.\n", children_count); } }
static const char *block_on_write(void) { char buf[PIPE_BUF+4]; for (int i = 0; i < PIPE_BUF+4; i++) buf[i] = "pipe"[i % 4]; run_child(bow_child); if (write(write_end, buf, PIPE_BUF+4) != PIPE_BUF+4) return "write"; return wait_for_child(); }
static const char *block_on_read(void) { char buf[4]; if (run_child(bor_child)) return "run_child"; if (read(read_end, buf, 4) != 4) return "read"; if (memcmp(buf, "pipe", 4)) return "memcmp"; return wait_for_child(); }
int cpu_event_pinned_vs_ebb(void) { union pipe read_pipe, write_pipe; struct event event; int cpu, rc; pid_t pid; SKIP_IF(!ebb_is_supported()); cpu = pick_online_cpu(); FAIL_IF(cpu < 0); FAIL_IF(bind_to_cpu(cpu)); FAIL_IF(pipe(read_pipe.fds) == -1); FAIL_IF(pipe(write_pipe.fds) == -1); pid = fork(); if (pid == 0) { /* NB order of pipes looks reversed */ exit(ebb_child(write_pipe, read_pipe)); } /* We setup the cpu event first */ rc = setup_cpu_event(&event, cpu); if (rc) { kill_child_and_wait(pid); return rc; } /* Signal the child to install its EBB event and wait */ if (sync_with_child(read_pipe, write_pipe)) /* If it fails, wait for it to exit */ goto wait; /* Signal the child to run */ FAIL_IF(sync_with_child(read_pipe, write_pipe)); wait: /* We expect it to fail to read the event */ FAIL_IF(wait_for_child(pid) != 2); FAIL_IF(event_disable(&event)); FAIL_IF(event_read(&event)); event_report(&event); /* The cpu event should have run */ FAIL_IF(event.result.value == 0); FAIL_IF(event.result.enabled != event.result.running); return 0; }
void go_daemon() { daemon_pid = fork(); if (daemon_pid == -1) fatal("fork: %s", strerror(errno)); if (daemon_pid) { if (o_wait) exit(wait_for_child()); exit(0); } if (setsid() == -1) fatal("setsid: %s", strerror(errno)); if (!o_wait) reopen_all(); }
static int create_child(int *pipe_read, int max_fd, int *child_socks) { pid_t pid; int socks[max_fd]; int i; int fds[2]; int ret; if (pipe(fds) < 0){ perror("pipe"); return -1; } pid = fork(); if (pid < 0) return -1; if (pid == 0) { //close(fds[0]); close_fds_except_pipe(fds[1], max_fd); for (i = 0; i < max_fd; i++) { socks[i] = create_icmp_socket(); if (socks[i] < 0) { //printf("\ncan not create socket!\n"); break; } } printf("child create %d sockets!\n", i); write(fds[1], &i, sizeof(int)); while (1) { sleep(6); } exit(0); } /* parent process */ close(fds[1]); *pipe_read = fds[0]; ret = wait_for_child(fds[0], child_socks); if (ret != 0) return -1; return pid; }
int task_event_vs_ebb(void) { union pipe read_pipe, write_pipe; struct event event; pid_t pid; int rc; SKIP_IF(!ebb_is_supported()); FAIL_IF(pipe(read_pipe.fds) == -1); FAIL_IF(pipe(write_pipe.fds) == -1); pid = fork(); if (pid == 0) { /* NB order of pipes looks reversed */ exit(ebb_child(write_pipe, read_pipe)); } /* We setup the task event first */ rc = setup_child_event(&event, pid); if (rc) { kill_child_and_wait(pid); return rc; } /* Signal the child to install its EBB event and wait */ if (sync_with_child(read_pipe, write_pipe)) /* If it fails, wait for it to exit */ goto wait; /* Signal the child to run */ FAIL_IF(sync_with_child(read_pipe, write_pipe)); wait: /* The EBB event should push the task event off so the child should succeed */ FAIL_IF(wait_for_child(pid)); FAIL_IF(event_disable(&event)); FAIL_IF(event_read(&event)); event_report(&event); /* The task event may have run, or not so we can't assert anything about it */ return 0; }
int exec_command (const std::vector<std::string>& command, std::ostream& output) { HANDLE stdout_pipe_reader = NULL; HANDLE stdout_pipe_writer = NULL; SECURITY_ATTRIBUTES sec_attr; // Set the bInheritHandle flag so pipe handles are inherited. sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES); sec_attr.bInheritHandle = TRUE; sec_attr.lpSecurityDescriptor = NULL; // Create a pipe for the child process's STDOUT. if (!CreatePipe(&stdout_pipe_reader, &stdout_pipe_writer, &sec_attr, 0)) { throw System_error("CreatePipe", "", GetLastError()); } // Ensure the read handle to the pipe for STDOUT is not inherited. if (!SetHandleInformation(stdout_pipe_reader, HANDLE_FLAG_INHERIT, 0)) { throw System_error("SetHandleInformation", "", GetLastError()); } HANDLE child_handle = spawn_command(command, NULL, stdout_pipe_writer, NULL); CloseHandle(stdout_pipe_writer); // Read from stdout_pipe_reader. // Note that ReadFile on a pipe may return with bytes_read==0 if the other // end of the pipe writes zero bytes, so don't break out of the read loop // when this happens. When the other end of the pipe closes, ReadFile // fails with ERROR_BROKEN_PIPE. char buffer[1024]; DWORD bytes_read; while (ReadFile(stdout_pipe_reader, buffer, sizeof(buffer), &bytes_read, NULL)) { output.write(buffer, bytes_read); } const DWORD read_error = GetLastError(); if (read_error != ERROR_BROKEN_PIPE) { throw System_error("ReadFile", "", read_error); } CloseHandle(stdout_pipe_reader); int exit_code = wait_for_child(child_handle); CloseHandle(child_handle); return exit_code; }
int start_process(const std::string& app_name, char* const args[], const std::string& outputfile, const std::string& ip) { static int counter = 0; pid_t pid = fork(); if (pid == 0) { // child int fid = open(outputfile.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); if (fid == -1) { std::cerr << "could not open output file \"" << outputfile << "\" Reason: " << strerror(errno) << std::endl; exit(1); } dup2( fid, STDOUT_FILENO ); dup2( fid, STDERR_FILENO ); close(fid); execvp(app_name.c_str(), args); // should never get here std::cerr << "Failed to exec " << app_name << ": " << strerror(errno) << std::endl; // should never get here exit(255); } else if (pid == -1) { std::cerr << "Error forking a new process: " << strerror(errno) << std::endl; return -1; } else { // parent counter++; if (counter % 100 == 0) { // sleep for some time to give the already started processes some time to finish // this should reduce the number struct timespec wait = { 0, 200000000 }; nanosleep(&wait, NULL); } started_processes[pid] = ip; started_counter++; // check if any of the processes already finished // if one of them already finished, then collect its // result before spawning new processe wait_for_child(WNOHANG); } }
void perfmon_init(void) { size_t i; long nr; if (cpu_type == CPU_TIMER_INT) return; nr = sysconf(_SC_NPROCESSORS_ONLN); if (nr == -1) { fprintf(stderr, "Couldn't determine number of CPUs.\n"); exit(EXIT_FAILURE); } nr_cpus = nr; children = xmalloc(sizeof(struct child) * nr_cpus); for (i = 0; i < nr_cpus; ++i) { int ret; if (pipe(children[i].up_pipe)) { perror("Couldn't create child pipe.\n"); exit(EXIT_FAILURE); } // ret = fork(); ret = vfork(); if (ret == -1) { fprintf(stderr, "Couldn't fork perfmon child.\n"); exit(EXIT_FAILURE); } else if (ret == 0) { printf("Running perfmon child on CPU%d.\n", (int)i); fflush(stdout); run_child(i); } else { children[i].pid = ret; printf("Waiting on CPU%d\n", (int)i); wait_for_child(&children[i]); } } }
int exec_command_with_input (const std::vector<std::string>& command, const char* p, size_t len) { HANDLE stdin_pipe_reader = NULL; HANDLE stdin_pipe_writer = NULL; SECURITY_ATTRIBUTES sec_attr; // Set the bInheritHandle flag so pipe handles are inherited. sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES); sec_attr.bInheritHandle = TRUE; sec_attr.lpSecurityDescriptor = NULL; // Create a pipe for the child process's STDIN. if (!CreatePipe(&stdin_pipe_reader, &stdin_pipe_writer, &sec_attr, 0)) { throw System_error("CreatePipe", "", GetLastError()); } // Ensure the write handle to the pipe for STDIN is not inherited. if (!SetHandleInformation(stdin_pipe_writer, HANDLE_FLAG_INHERIT, 0)) { throw System_error("SetHandleInformation", "", GetLastError()); } HANDLE child_handle = spawn_command(command, stdin_pipe_reader, NULL, NULL); CloseHandle(stdin_pipe_reader); // Write to stdin_pipe_writer. while (len > 0) { DWORD bytes_written; if (!WriteFile(stdin_pipe_writer, p, len, &bytes_written, NULL)) { throw System_error("WriteFile", "", GetLastError()); } p += bytes_written; len -= bytes_written; } CloseHandle(stdin_pipe_writer); int exit_code = wait_for_child(child_handle); CloseHandle(child_handle); return exit_code; }
EXPORTED int run_command(const char *argv0, ...) { va_list va; const char *p; strarray_t argv = STRARRAY_INITIALIZER; pid_t pid; int r = 0; strarray_append(&argv, argv0); va_start(va, argv0); while ((p = va_arg(va, const char *))) strarray_append(&argv, p); va_end(va); pid = fork(); if (pid < 0) { syslog(LOG_ERR, "Failed to fork: %m"); r = IMAP_SYS_ERROR; goto out; } if (!pid) { /* in child */ r = execv(argv0, argv.data); syslog(LOG_ERR, "Failed to execute %s: %m", argv0); exit(1); } else { /* in parent */ r = wait_for_child(argv0, pid); } out: strarray_fini(&argv); return r; }
/* Tests we can setup an EBB on our child - if it's expecting it */ int ebb_on_willing_child(void) { union pipe read_pipe, write_pipe; struct event event; pid_t pid; FAIL_IF(pipe(read_pipe.fds) == -1); FAIL_IF(pipe(write_pipe.fds) == -1); pid = fork(); if (pid == 0) { /* NB order of pipes looks reversed */ exit(victim_child(write_pipe, read_pipe)); } /* Signal the child to setup its EBB handler */ FAIL_IF(sync_with_child(read_pipe, write_pipe)); /* Child is running now */ event_init_named(&event, 0x1001e, "cycles"); event_leader_ebb_init(&event); event.attr.exclude_kernel = 1; event.attr.exclude_hv = 1; event.attr.exclude_idle = 1; FAIL_IF(event_open_with_pid(&event, pid)); FAIL_IF(ebb_event_enable(&event)); /* Child show now take EBBs and then exit */ FAIL_IF(wait_for_child(pid)); event_close(&event); return 0; }
int main(int argc, char **argv) { int ch, error; bool Vflag = false, vflag = false; const char *certpath = NULL, *keypath = NULL, *outpath = NULL, *inpath = NULL; FILE *certfp = NULL, *keyfp = NULL; X509 *cert = NULL; EVP_PKEY *key = NULL; pid_t pid; int pipefds[2]; while ((ch = getopt(argc, argv, "Vc:k:o:v")) != -1) { switch (ch) { case 'V': Vflag = true; break; case 'c': certpath = checked_strdup(optarg); break; case 'k': keypath = checked_strdup(optarg); break; case 'o': outpath = checked_strdup(optarg); break; case 'v': vflag = true; break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1) usage(); if (Vflag) { if (certpath != NULL) errx(1, "-V and -c are mutually exclusive"); if (keypath != NULL) errx(1, "-V and -k are mutually exclusive"); if (outpath != NULL) errx(1, "-V and -o are mutually exclusive"); } else { if (certpath == NULL) errx(1, "-c option is mandatory"); if (keypath == NULL) errx(1, "-k option is mandatory"); if (outpath == NULL) errx(1, "-o option is mandatory"); } inpath = argv[0]; OPENSSL_config(NULL); ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); error = pipe(pipefds); if (error != 0) err(1, "pipe"); pid = fork(); if (pid < 0) err(1, "fork"); if (pid == 0) return (child(inpath, outpath, pipefds[1], Vflag, vflag)); if (!Vflag) { certfp = checked_fopen(certpath, "r"); cert = PEM_read_X509(certfp, NULL, NULL, NULL); if (cert == NULL) { ERR_print_errors_fp(stderr); errx(1, "failed to load certificate from %s", certpath); } keyfp = checked_fopen(keypath, "r"); key = PEM_read_PrivateKey(keyfp, NULL, NULL, NULL); if (key == NULL) { ERR_print_errors_fp(stderr); errx(1, "failed to load private key from %s", keypath); } sign(cert, key, pipefds[0]); } return (wait_for_child(pid)); }
/* * basil_request - issue BASIL request and parse response * @bp: method-dependent parse data to guide the parsing process * * Returns 0 if ok, a negative %basil_error otherwise. */ int basil_request(struct basil_parse_data *bp) { int to_child, from_child; int ec, i, rc = -BE_UNKNOWN; FILE *apbasil; pid_t pid = -1; pthread_t thread; pthread_attr_t attr; int time_it_out = 1; DEF_TIMERS; if (log_sel == -1) _init_log_config(); if (!cray_conf->apbasil) { error("No alps client defined"); return 0; } if ((cray_conf->apbasil_timeout == 0) || (cray_conf->apbasil_timeout == (uint16_t) NO_VAL)) { debug2("No ApbasilTimeout configured (%u)", cray_conf->apbasil_timeout); time_it_out = 0; } else { slurm_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); } assert(bp->version < BV_MAX); assert(bp->method > BM_none && bp->method < BM_MAX); START_TIMER; for (i = 0; ((i < 10) && (pid < 0)); i++) { if (i) usleep(100000); pid = popen2(cray_conf->apbasil, &to_child, &from_child, true); } if (pid < 0) fatal("popen2(\"%s\", ...)", cray_conf->apbasil); if (time_it_out) { pthread_create(&thread, &attr, _timer_func, (void*)&pid); } /* write out request */ apbasil = fdopen(to_child, "w"); if (apbasil == NULL) fatal("fdopen(): %s", strerror(errno)); setlinebuf(apbasil); _write_xml(apbasil, "<?xml version=\"1.0\"?>\n" "<BasilRequest protocol=\"%s\" method=\"%s\" ", bv_names[bp->version], bm_names[bp->method]); switch (bp->method) { case BM_engine: _write_xml(apbasil, "type=\"ENGINE\"/>"); break; case BM_inventory: _write_xml(apbasil, "type=\"INVENTORY\"/>"); break; case BM_reserve: _write_xml(apbasil, ">\n"); _rsvn_write_reserve_xml(apbasil, bp->mdata.res, bp->version); break; case BM_confirm: if (bp->version == BV_1_0 && *bp->mdata.res->batch_id != '\0') _write_xml(apbasil, "job_name=\"%s\" ", bp->mdata.res->batch_id); _write_xml(apbasil, "reservation_id=\"%u\" %s=\"%llu\"/>\n", bp->mdata.res->rsvn_id, bp->version >= BV_3_1 ? "pagg_id" : "admin_cookie", (unsigned long long)bp->mdata.res->pagg_id); break; case BM_release: _write_xml(apbasil, "reservation_id=\"%u\"/>\n", bp->mdata.res->rsvn_id); break; case BM_switch: { char *suspend = bp->mdata.res->suspended ? "OUT" : "IN"; _write_xml(apbasil, ">\n"); _write_xml(apbasil, " <ReservationArray>\n"); _write_xml(apbasil, " <Reservation reservation_id=\"%u\" " "action=\"%s\"/>\n", bp->mdata.res->rsvn_id, suspend); _write_xml(apbasil, " </ReservationArray>\n"); _write_xml(apbasil, "</BasilRequest>\n"); } break; default: /* ignore BM_none, BM_MAX, and BM_UNKNOWN covered above */ break; } if (fclose(apbasil) < 0) /* also closes to_child */ error("fclose(apbasil): %s", strerror(errno)); rc = parse_basil(bp, from_child); ec = wait_for_child(pid); if (time_it_out) { slurm_attr_destroy(&attr); debug2("Killing the timer thread."); pthread_mutex_lock(&timer_lock); pthread_cond_broadcast(&timer_cond); pthread_mutex_unlock(&timer_lock); } END_TIMER; if (ec) { error("%s child process for BASIL %s method exited with %d", cray_conf->apbasil, bm_names[bp->method], ec); } else if (DELTA_TIMER > 5000000) { /* 5 seconds limit */ info("%s child process for BASIL %s method time %s", cray_conf->apbasil, bm_names[bp->method], TIME_STR); } return rc; }
/* * basil_request - issue BASIL request and parse response * @bp: method-dependent parse data to guide the parsing process * * Returns 0 if ok, a negative %basil_error otherwise. */ int basil_request(struct basil_parse_data *bp) { int to_child, from_child; int ec, rc = -BE_UNKNOWN; FILE *apbasil; pid_t pid; if (log_sel == -1) _init_log_config(); if (!cray_conf->apbasil) { error("No alps client defined"); return 0; } assert(bp->version < BV_MAX); assert(bp->method > BM_none && bp->method < BM_MAX); pid = popen2(cray_conf->apbasil, &to_child, &from_child, true); if (pid < 0) fatal("popen2(\"%s\", ...)", cray_conf->apbasil); /* write out request */ apbasil = fdopen(to_child, "w"); if (apbasil == NULL) fatal("fdopen(): %s", strerror(errno)); setlinebuf(apbasil); _write_xml(apbasil, "<?xml version=\"1.0\"?>\n" "<BasilRequest protocol=\"%s\" method=\"%s\" ", bv_names[bp->version], bm_names[bp->method]); switch (bp->method) { case BM_engine: _write_xml(apbasil, "type=\"ENGINE\"/>"); break; case BM_inventory: _write_xml(apbasil, "type=\"INVENTORY\"/>"); break; case BM_reserve: _write_xml(apbasil, ">\n"); _rsvn_write_reserve_xml(apbasil, bp->mdata.res); break; case BM_confirm: if (bp->version == BV_1_0 && *bp->mdata.res->batch_id != '\0') _write_xml(apbasil, "job_name=\"%s\" ", bp->mdata.res->batch_id); _write_xml(apbasil, "reservation_id=\"%u\" %s=\"%llu\"/>\n", bp->mdata.res->rsvn_id, bp->version >= BV_3_1 ? "pagg_id" : "admin_cookie", (unsigned long long)bp->mdata.res->pagg_id); break; case BM_release: _write_xml(apbasil, "reservation_id=\"%u\"/>\n", bp->mdata.res->rsvn_id); break; case BM_switch: { char *suspend = bp->mdata.res->suspended ? "OUT" : "IN"; _write_xml(apbasil, ">\n"); _write_xml(apbasil, " <ReservationArray>\n"); _write_xml(apbasil, " <Reservation reservation_id=\"%u\" " "action=\"%s\"/>\n", bp->mdata.res->rsvn_id, suspend); _write_xml(apbasil, " </ReservationArray>\n"); _write_xml(apbasil, "</BasilRequest>\n"); } break; default: /* ignore BM_none, BM_MAX, and BM_UNKNOWN covered above */ break; } if (fclose(apbasil) < 0) /* also closes to_child */ error("fclose(apbasil): %s", strerror(errno)); rc = parse_basil(bp, from_child); ec = wait_for_child(pid); if (ec) { error("%s child process for BASIL %s method exited with %d", cray_conf->apbasil, bm_names[bp->method], ec); } return rc; }
/** * execute the checkEnv command. */ void cmd_check_env(char *args[ARGS_SIZE]) { int fd_descriptor_env_sort[2]; int fd_descriptor_sort_pager[2]; int fd_descriptor_grep_sort[2]; pid_t env_child, sort_child, grep_child, pager_child; int grep = FALSE; int return_value; sighold(SIGCHLD); create_pipe(fd_descriptor_env_sort); create_pipe(fd_descriptor_sort_pager); create_pipe(fd_descriptor_grep_sort); env_child = fork(); if (env_child == 0) { return_value = dup2(fd_descriptor_env_sort[PIPE_WRITE], STDOUT_FILENO); check_return_value(return_value, "Error: cannot dup2 1"); close_all_pipes(fd_descriptor_env_sort, fd_descriptor_sort_pager, fd_descriptor_grep_sort); print_environment(); exit(EXIT_SUCCESS); } else if (env_child == -1) { perror("Error forking."); exit(EXIT_FAILURE); } if(args[1] != NULL) { grep = TRUE; grep_child = fork(); if(grep_child == 0) { return_value = dup2(fd_descriptor_env_sort[PIPE_READ], STDIN_FILENO); check_return_value(return_value, "Error: cannot dup2 2"); return_value = dup2(fd_descriptor_grep_sort[PIPE_WRITE], STDOUT_FILENO); check_return_value(return_value, "Error: cannot dup2 3"); close_all_pipes(fd_descriptor_env_sort, fd_descriptor_sort_pager, fd_descriptor_grep_sort); args[0] = "grep"; return_value = execvp(args[0], args); check_return_value(return_value, "Error: execution failed."); } else if(grep_child == -1){ perror("Error forking."); exit(EXIT_FAILURE); } } sort_child = fork(); if (sort_child == 0) { char * argp[] = {"sort", NULL}; if(grep == TRUE) { return_value = dup2(fd_descriptor_grep_sort[PIPE_READ], STDIN_FILENO); check_return_value(return_value, "Error: cannot dup2 3"); } else { return_value = dup2(fd_descriptor_env_sort[PIPE_READ], STDIN_FILENO); check_return_value(return_value, "Error: cannot dup2 4"); } return_value = dup2(fd_descriptor_sort_pager[PIPE_WRITE], STDOUT_FILENO); check_return_value(return_value, "Error: cannot dup2 5"); close_all_pipes(fd_descriptor_env_sort, fd_descriptor_sort_pager, fd_descriptor_grep_sort); args[0] = "sort"; return_value = execvp(args[0], argp); check_return_value(return_value, "Error: execution failed."); } else if (sort_child == -1) { perror("Error forking."); exit(EXIT_FAILURE); } pager_child = fork(); if (pager_child == 0) { char * argp[] = {"less", NULL}; return_value = dup2(fd_descriptor_sort_pager[PIPE_READ], STDIN_FILENO); check_return_value(return_value, "Error: cannot dup2 6"); close_all_pipes(fd_descriptor_env_sort, fd_descriptor_sort_pager, fd_descriptor_grep_sort); if(getenv("PAGER") != NULL) { argp[0] = getenv("PAGER"); } return_value = execvp(argp[0], argp); check_return_value(return_value, "Error: execution failed."); } else if (pager_child == -1) { perror("Error forking."); exit(EXIT_FAILURE); } close_all_pipes(fd_descriptor_env_sort, fd_descriptor_sort_pager, fd_descriptor_grep_sort); wait_for_child(); wait_for_child(); wait_for_child(); if(grep == TRUE) wait_for_child(); sigrelse(SIGCHLD); }
int kill_child_and_wait(pid_t child_pid) { kill(child_pid, SIGTERM); return wait_for_child(child_pid); }
void testrunner_t::run_test(testfn_t *fn) { running_ = fn; nrun_++; int pipefd[2]; if (pipe(pipefd) < 0) { perror("pipe"); return; } dmsg("Forking"); pid_t pid = fork(); if (pid < 0) { perror("fork"); close(pipefd[PIPE_READ]); close(pipefd[PIPE_WRITE]); running_ = 0; return; } if (pid == 0) { /* child process - return and run the test code, dtor will exit. */ dmsg("In child process"); close(pipefd[PIPE_READ]); /* record the write end of the status pipe for _check() */ status_pipe = pipefd[PIPE_WRITE]; /* run the fixtures and test function */ fn->run(); /* send a success message */ char buf[STATUS_LEN]; snprintf(buf, sizeof(buf), "+PASS %s.%s", fn->suite(), fn->name()); retry_write(status_pipe, buf, strlen(buf)); dmsg("Child process exiting normally"); exit(0); } else { /* parent process - read status and wait for the child to finish */ dmsg("In parent process"); close(pipefd[PIPE_WRITE]); /* we expect at most one status line, from either a * _check() failure or a successful test. */ char buf[STATUS_LEN]; if (read_status(buf, sizeof(buf), pipefd[PIPE_READ]) < 0) { running_ = 0; return; } close(pipefd[PIPE_READ]); /* wait the for child process to exit */ int r = wait_for_child(pid); /* diagnose test failure */ if (r < 0 && r != -ESRCH) { running_ = 0; return; } if (r == 0 && buf[0] == '+') { fprintf(stderr, "PASS %s.%s\n", fn->suite(), fn->name()); npass_++; } else if (buf[0] != '\0') { fprintf(stderr, "Test %s.%s failed:\n", fn->suite(), fn->name()); fputs(buf+1, stderr); } } running_ = 0; }
static int run_in_parallel(char *script, struct cmdargs *args, int argc, char *argv[], int optind) { int max_procs = DEFAULT_MAX_PROCS; long system_max_procs; int active_children = 0; pid_t p, child_group; int i, ret = 0, saved_ret; struct sigaction sa_parent, sa_saved[4]; if (args->max_procs) { if (sscanf(args->max_procs, "%d", &max_procs) != 1 || max_procs == 0) { fprintf(stderr, "%s: invalid value for --limit: %s - using default.\n", getenv("_"), args->max_procs); max_procs = DEFAULT_MAX_PROCS; } } /* sanity check - make sure the maximum number of processes is less than the system limit. account for the fact that this application and the shell that invoked it count against that limit. it's still unsafe to specify a really big value (slightly less so if the code to be executed doesn't spawn any more procs). */ system_max_procs = sysconf(_SC_CHILD_MAX); if (system_max_procs > 0 && max_procs > system_max_procs - 2) max_procs = system_max_procs - 2; /* all children will be members of a new group having this * process's PID. so if it's necessary to kill all of the * children, that can be achieved by killing all members of * child_group. the parent process should not be a member of * that group if/when that happens, but it needs to be the * leader of the group while children are added to it. */ child_group = getpid(); setpgid(0, child_group); /* set up signal handling for the parent. */ sigemptyset(&sa_parent.sa_mask); sa_parent.sa_handler = sig_handler; sa_parent.sa_flags = 0; if (sigaction(SIGINT, &sa_parent, &(sa_saved[0])) < 0) warn("sigaction(SIGINT)"); if (sigaction(SIGHUP, &sa_parent, &(sa_saved[1])) < 0) warn("sigaction(SIGHUP)"); if (sigaction(SIGTERM, &sa_parent, &(sa_saved[2])) < 0) warn("sigaction(SIGTERM)"); if (sigaction(SIGABRT, &sa_parent, &(sa_saved[3])) < 0) warn("sigaction(SIGABRT)"); for (i = optind; i < argc; i++) { p = fork(); if (p < 0) { warn("fork error"); return -1; } else if (p == 0) { /* in the child proc. * restore signal dispositions, * set the process group, * set the user-provided env var, * and exec the process. */ if (sigaction(SIGINT, &(sa_saved[0]), NULL) < 0) warn("(child) sigaction(SIGINT)"); if (sigaction(SIGHUP, &(sa_saved[1]), NULL) < 0) warn("(child) sigaction(SIGHUP)"); if (sigaction(SIGTERM, &(sa_saved[2]), NULL) < 0) warn("(child) sigaction(SIGTERM)"); if (sigaction(SIGABRT, &(sa_saved[3]), NULL) < 0) warn("(child) sigaction(SIGABRT)"); if (setpgid(0, child_group) != 0) { warn("(child) setting group ID to the parent"); } setenv(args->variable, argv[i], 1); execl(getenv("SHELL"), getenv("SHELL"), script, NULL); } else { /* in the parent proc */ setpgid(p, child_group); active_children++; if (active_children >= max_procs) { DEBUG_PRINT("limit reached: waiting for a child to exit."); ret = wait_for_child(0); } else { /* just check to see if any children are waiting to be reaped. */ ret = wait_for_child(WNOHANG); #ifdef CRUSH_DEBUG if (ret >= 0) { DEBUG_PRINT("a child has been reaped."); } #endif } /* ret == -1 means there were no children. * if one of the children exited with an * error condition (i.e. non-zero), stop * spawning new processes. */ if (ret >= 0) { active_children--; if (ret != 0) break; } else if (ret != -1) { break; } } } saved_ret = (ret == -1 ? 0 : ret); while (active_children > 0) { DEBUG_PRINT("cleanup: waiting for a child to exit."); ret = wait_for_child(0); if (ret != 0 && ret != -1) saved_ret = ret; if (ret == -1) active_children = 0; else active_children--; } return saved_ret; }
int main(int argc, char **argv) { int maxjobs = -1; int curjobs = 0; double maxload = -1; int argsatonce = 1; int opt; char **command = calloc(sizeof(char*), argc); char **arguments = NULL; int argidx = 0; int arglen = 0; int cidx = 0; int returncode = 0; int replace_cb = 0; int stdout_fd = 1; int stderr_fd = 2; char *t; while ((argv[optind] && strcmp(argv[optind], "--") != 0) && (opt = getopt(argc, argv, "+hij:l:n:")) != -1) { switch (opt) { case 'h': usage(); break; case 'i': replace_cb = 1; break; case 'j': errno = 0; maxjobs = strtoul(optarg, &t, 0); if (errno != 0 || (t-optarg) != strlen(optarg)) { fprintf(stderr, "option '%s' is not a number\n", optarg); exit(2); } break; case 'l': errno = 0; maxload = strtod(optarg, &t); if (errno != 0 || (t-optarg) != strlen(optarg)) { fprintf(stderr, "option '%s' is not a number\n", optarg); exit(2); } break; case 'n': errno = 0; argsatonce = strtoul(optarg, &t, 0); if (errno != 0 || argsatonce < 1 || (t-optarg) != strlen(optarg)) { fprintf(stderr, "option '%s' is not a positive number\n", optarg); exit(2); } break; default: /* ’?’ */ usage(); break; } } if (replace_cb && argsatonce > 1) { fprintf(stderr, "options -i and -n are incomaptible\n"); exit(2); } if (maxjobs < 0) { #ifdef _SC_NPROCESSORS_ONLN maxjobs = sysconf(_SC_NPROCESSORS_ONLN); #else #warning Cannot autodetect number of CPUS on this system: _SC_NPROCESSORS_ONLN not defined. maxjobs = 1; #endif } while (optind < argc) { if (strcmp(argv[optind], "--") == 0) { int i; optind++; arglen = argc - optind; arguments = calloc(sizeof(char *), arglen); if (! arguments) { exit(1); } for (i = 0; i < arglen; i++) { arguments[i] = strdup(argv[optind + i]); } optind += i; } else { command[cidx] = strdup(argv[optind]); cidx++; } optind++; } if (argsatonce > 1 && ! command[0]) { fprintf(stderr, "option -n cannot be used without a command\n"); exit(2); } pipe_child_stdout = create_pipe_child(&stdout_fd, 1); pipe_child_stderr = create_pipe_child(&stderr_fd, 2); if ((pipe_child_stdout < 0) || (pipe_child_stderr < 0)) exit(1); while (argidx < arglen) { double load; getloadavg(&load, 1); if ((maxjobs == 0 || curjobs < maxjobs) && (maxload < 0 || load < maxload)) { if (argsatonce > arglen - argidx) argsatonce = arglen - argidx; exec_child(command, arguments + argidx, replace_cb, argsatonce, stdout_fd, stderr_fd); argidx += argsatonce; curjobs++; } if (maxjobs == 0 || curjobs == maxjobs) { returncode |= wait_for_child(0); curjobs--; } if (maxload > 0 && load >= maxload) { int r; sleep(1); /* XXX We should have a better * heurestic than this */ r = wait_for_child(WNOHANG); if (r > 0) returncode |= r; if (r != -1) curjobs--; } } while (curjobs > 0) { returncode |= wait_for_child(0); curjobs--; } if (pipe_child_stdout) { kill(pipe_child_stdout, SIGKILL); wait_for_child(0); } if (pipe_child_stderr) { kill(pipe_child_stderr, SIGKILL); wait_for_child(0); } return returncode; }