RETSIGTYPE child_signal(int sig) { #ifdef BACKGROUND_POST /* * reap background posting process */ if(ps_global->post && ps_global->post->pid) { pid_t pid; int es; pid = process_reap(ps_global->post->pid, &es, PR_NOHANG); if(pid == ps_global->post->pid) { ps_global->post->status = es; ps_global->post->pid = 0; return; } else if(pid < 0 && errno != EINTR) { fs_give((void **) &ps_global->post); } } #endif /* BACKGROUND_POST */ child_signalled = 1; if(child_jump) longjmp(child_state, 1); }
int run_test(const char* test, int timeout, int benchmark_output, int test_count) { char errmsg[1024] = "no error"; process_info_t processes[1024]; process_info_t *main_proc; task_entry_t* task; int process_count; int result; int status; int i; status = 255; main_proc = NULL; process_count = 0; #ifndef _WIN32 /* Clean up stale socket from previous run. */ remove(TEST_PIPENAME); #endif /* If it's a helper the user asks for, start it directly. */ for (task = TASKS; task->main; task++) { if (task->is_helper && strcmp(test, task->process_name) == 0) { return task->main(); } } /* Start the helpers first. */ for (task = TASKS; task->main; task++) { if (strcmp(test, task->task_name) != 0) { continue; } /* Skip the test itself. */ if (!task->is_helper) { continue; } if (process_start(task->task_name, task->process_name, &processes[process_count], 1 /* is_helper */) == -1) { snprintf(errmsg, sizeof errmsg, "Process `%s` failed to start.", task->process_name); goto out; } process_count++; } /* Give the helpers time to settle. Race-y, fix this. */ uv_sleep(250); /* Now start the test itself. */ for (task = TASKS; task->main; task++) { if (strcmp(test, task->task_name) != 0) { continue; } if (task->is_helper) { continue; } if (process_start(task->task_name, task->process_name, &processes[process_count], 0 /* !is_helper */) == -1) { snprintf(errmsg, sizeof errmsg, "Process `%s` failed to start.", task->process_name); goto out; } main_proc = &processes[process_count]; process_count++; break; } if (main_proc == NULL) { snprintf(errmsg, sizeof errmsg, "No test with that name: %s", test); goto out; } result = process_wait(main_proc, 1, timeout); if (result == -1) { FATAL("process_wait failed"); } else if (result == -2) { /* Don't have to clean up the process, process_wait() has killed it. */ snprintf(errmsg, sizeof errmsg, "timeout"); goto out; } status = process_reap(main_proc); if (status != 0) { snprintf(errmsg, sizeof errmsg, "exit code %d", status); goto out; } if (benchmark_output) { /* Give the helpers time to clean up their act. */ uv_sleep(1000); } out: /* Reap running processes except the main process, it's already dead. */ for (i = 0; i < process_count - 1; i++) { process_terminate(&processes[i]); } if (process_count > 0 && process_wait(processes, process_count - 1, -1) < 0) { FATAL("process_wait failed"); } /* Show error and output from processes if the test failed. */ if (status != 0 || task->show_output) { if (tap_output) { LOGF("not ok %d - %s\n#", test_count, test); } else if (status != 0) { LOGF("\n`%s` failed: %s\n", test, errmsg); } else { LOGF("\n"); } for (i = 0; i < process_count; i++) { switch (process_output_size(&processes[i])) { case -1: LOGF("Output from process `%s`: (unavailable)\n", process_get_name(&processes[i])); break; case 0: LOGF("Output from process `%s`: (no output)\n", process_get_name(&processes[i])); break; default: LOGF("Output from process `%s`:\n", process_get_name(&processes[i])); process_copy_output(&processes[i], fileno(stderr)); break; } } if (!tap_output) { LOG("=============================================================\n"); } /* In benchmark mode show concise output from the main process. */ } else if (benchmark_output) { switch (process_output_size(main_proc)) { case -1: LOGF("%s: (unavailable)\n", test); break; case 0: LOGF("%s: (no output)\n", test); break; default: for (i = 0; i < process_count; i++) { process_copy_output(&processes[i], fileno(stderr)); } break; } } else if (tap_output) { LOGF("ok %d - %s\n", test_count, test); } /* Clean up all process handles. */ for (i = 0; i < process_count; i++) { process_cleanup(&processes[i]); } return status; }
// // 如何处理各种Command呢? // 一般用于不同对象之间的通信,包括cross thread的通信 // 各种相关的函数实现已经定义好 // void zmq::object_t::process_command(command_t &cmd_) { switch (cmd_.type) { case command_t::activate_read: process_activate_read(); break; case command_t::activate_write: process_activate_write(cmd_.args.activate_write.msgs_read); break; case command_t::stop: process_stop(); break; case command_t::plug: process_plug(); process_seqnum(); break; case command_t::own: process_own(cmd_.args.own.object); process_seqnum(); break; case command_t::attach: process_attach(cmd_.args.attach.engine); process_seqnum(); break; case command_t::bind: process_bind(cmd_.args.bind.pipe); process_seqnum(); break; case command_t::hiccup: process_hiccup(cmd_.args.hiccup.pipe); break; case command_t::pipe_term: process_pipe_term(); break; case command_t::pipe_term_ack: process_pipe_term_ack(); break; case command_t::term_req: process_term_req(cmd_.args.term_req.object); break; case command_t::term: process_term(cmd_.args.term.linger); break; case command_t::term_ack: process_term_ack(); break; case command_t::reap: process_reap(cmd_.args.reap.socket); break; case command_t::reaped: process_reaped(); break; case command_t::inproc_connected: process_seqnum(); break; case command_t::done: default: zmq_assert (false); } }
/*---------------------------------------------------------------------- Close pipe previously allocated and wait for child's death Args: syspipe -- address of pointer to struct returned by open_system_pipe exitval -- return exit status here. Returns: Two modes of return values for backcompat. If exitval == NULL returns exit status of child or -1 if invalid syspipe If exitval != NULL returns -1 if invalid syspipe or 0 if ok. In that case, exitval of child is returned in exitval ----*/ int close_system_pipe(PIPE_S **syspipe, int *exitval, void (*pipecb_f) (PIPE_S *, int, void *)) { #ifdef _WINDOWS int rv = 0; unsigned flags = 0; if(!(syspipe && *syspipe)) return(-1); if((*syspipe)->mode & PIPE_STDERR) flags |= MSWIN_EAW_CAPT_STDERR; if(((*syspipe)->mode & PIPE_WRITE) && (*syspipe)->out.f){ fclose((*syspipe)->out.f); /* * PIPE_WRITE can't start process till now, all the others * will have already run */ if(pipe_mswin_exec_wrapper("pipe command", (*syspipe), flags, pipecb_f, NULL)) /* some horrible error just occurred */ rv = -1; } else if((*syspipe)->mode & PIPE_READ) if((*syspipe)->in.f) fclose((*syspipe)->in.f); if(exitval){ *exitval = (*syspipe)->exit_code; dprint((5, "Closed pipe: exitval=%d\n", *exitval)); } if((*syspipe)->infile) our_unlink((*syspipe)->infile); if((*syspipe)->outfile && (*syspipe)->deloutfile) our_unlink((*syspipe)->outfile); if(rv != -1 && !exitval) rv = (*syspipe)->exit_code; zot_pipe(syspipe); #ifdef DEBUG if(!exitval){ dprint((5, "Closed pipe: rv=%d\n", rv)); } #endif /* DEBUG */ return(rv); #else /* UNIX */ int status; if(!(syspipe && *syspipe)) return -1; if(((*syspipe)->mode) & PIPE_WRITE){ if(((*syspipe)->mode) & PIPE_DESC){ if((*syspipe)->out.d >= 0) close((*syspipe)->out.d); } else if((*syspipe)->out.f) fclose((*syspipe)->out.f); } if(((*syspipe)->mode) & PIPE_READ){ if(((*syspipe)->mode) & PIPE_DESC){ if((*syspipe)->in.d >= 0) close((*syspipe)->in.d); } else if((*syspipe)->in.f) fclose((*syspipe)->in.f); } if(pipecb_f) (*pipecb_f)(*syspipe, OSB_PRE_CLOSE, NULL); /* wait on the child */ (void) process_reap((*syspipe)->pid, &status, PR_NONE); /* restore original handlers... */ (void) signal(SIGINT, (*syspipe)->isig); (void) signal(SIGHUP, (*syspipe)->hsig); (void) signal(SIGQUIT, (*syspipe)->qsig); if((*syspipe)->timeout){ (void)signal(SIGALRM, (*syspipe)->alrm); alarm((*syspipe)->old_timeo); child_pid = 0; } if(pipecb_f) (*pipecb_f)(*syspipe, OSB_POST_CLOSE, NULL); zot_pipe(syspipe); if(exitval){ *exitval = status; return 0; } else{ return(status); } #endif /* UNIX */ }
/* * Runs all processes associated with a particular test or benchmark. * It returns 1 if the test succeeded, 0 if it failed. * If the test fails it prints diagnostic information. * If benchmark_output is nonzero, the output from the main process is * always shown. */ int run_task(task_entry_t *test, int timeout, int benchmark_output) { int i, result, success; char errmsg[256]; task_entry_t *helper; int process_count; process_info_t processes[MAX_PROCESSES]; process_info_t *main_process; success = 0; process_count = 0; /* Start all helpers for this test first. */ for (helper = (task_entry_t*)&TASKS; helper->main; helper++) { if (helper->is_helper && strcmp(test->task_name, helper->task_name) == 0) { if (process_start(helper->process_name, &processes[process_count]) == -1) { snprintf((char*)&errmsg, sizeof(errmsg), "process `%s` failed to start.", helper->process_name); goto finalize; } process_count++; } } /* Wait a little bit to allow servers to start. Racy. */ uv_sleep(50); /* Start the main test process. */ if (process_start(test->process_name, &processes[process_count]) == -1) { snprintf((char*)&errmsg, sizeof(errmsg), "process `%s` failed to start.", test->process_name); goto finalize; } main_process = &processes[process_count]; process_count++; /* Wait for the main process to terminate. */ result = process_wait(main_process, 1, timeout); if (result == -1) { FATAL("process_wait failed"); } else if (result == -2) { snprintf((char*)&errmsg, sizeof(errmsg), "timeout."); goto finalize; } /* Reap the main process. */ result = process_reap(main_process); if (result != 0) { snprintf((char*)&errmsg, sizeof(errmsg), "exit code %d.", result); goto finalize; } /* Yes! did it. */ success = 1; finalize: /* Kill all (helper) processes that are still running. */ for (i = 0; i < process_count; i++) { /* If terminate fails the process is probably already closed. */ process_terminate(&processes[i]); } /* Wait until all processes have really terminated. */ if (process_wait((process_info_t*)&processes, process_count, -1) < 0) { FATAL("process_wait failed"); } /* Show error and output from processes if the test failed. */ if (!success) { LOGF("\n`%s` failed: %s\n", test->task_name, errmsg); for (i = 0; i < process_count; i++) { switch (process_output_size(&processes[i])) { case -1: LOGF("Output from process `%s`: (unavailable)\n", process_get_name(&processes[i])); break; case 0: LOGF("Output from process `%s`: (no output)\n", process_get_name(&processes[i])); break; default: LOGF("Output from process `%s`:\n", process_get_name(&processes[i])); process_copy_output(&processes[i], fileno(stderr)); break; } } LOG("=============================================================\n"); /* In benchmark mode show concise output from the main process. */ } else if (benchmark_output) { switch (process_output_size(main_process)) { case -1: LOGF("%s: (unavailabe)\n", test->task_name); break; case 0: LOGF("%s: (no output)\n", test->task_name); break; default: //LOGF("%s: ", test->task_name); process_copy_output(main_process, fileno(stderr)); break; } } /* Clean up all process handles. */ for (i = 0; i < process_count; i++) { process_cleanup(&processes[i]); } return success; }
void zmq::object_t::process_command (command_t &cmd_) { switch (cmd_.type) { case command_t::activate_read: process_activate_read (); break; case command_t::activate_write: process_activate_write (cmd_.args.activate_write.msgs_read); break; case command_t::stop: process_stop (); break; case command_t::plug: process_plug (); process_seqnum (); break; case command_t::own: process_own (cmd_.args.own.object); process_seqnum (); break; case command_t::attach: process_attach (cmd_.args.attach.engine, cmd_.args.attach.peer_identity ? blob_t (cmd_.args.attach.peer_identity, cmd_.args.attach.peer_identity_size) : blob_t ()); process_seqnum (); break; case command_t::bind: process_bind (cmd_.args.bind.pipe, cmd_.args.bind.peer_identity ? blob_t (cmd_.args.bind.peer_identity, cmd_.args.bind.peer_identity_size) : blob_t ()); process_seqnum (); break; case command_t::hiccup: process_hiccup (cmd_.args.hiccup.pipe); break; case command_t::pipe_term: process_pipe_term (); break; case command_t::pipe_term_ack: process_pipe_term_ack (); break; case command_t::term_req: process_term_req (cmd_.args.term_req.object); break; case command_t::term: process_term (cmd_.args.term.linger); break; case command_t::term_ack: process_term_ack (); break; case command_t::reap: process_reap (cmd_.args.reap.socket); break; case command_t::reaped: process_reaped (); break; default: zmq_assert (false); } // The assumption here is that each command is processed once only, // so deallocating it after processing is all right. deallocate_command (&cmd_); }