void restart_child(int signal_status) { fprintf(stderr, "Aeternum received SIGUSR1, killing child.\n"); uv_process_kill(&child_req, SIGTERM); sleep(5); // Just `sleep` here, not doing anything important anyway. uv_process_kill(&child_req, SIGKILL); // Re-assign signal handler signal(SIGUSR1, restart_child); }
void handle_signal(int signal_status) { fprintf(stderr, "Aeternum kill by signal %d, exiting.\n", signal_status); uv_process_kill(&child_req, SIGTERM); sleep(5); // Just `sleep` here, not doing anything important anyway. uv_process_kill(&child_req, SIGKILL); if (opts.pidname) { cleanup_pid_file(opts.pidname); } exit(0); }
/// Releases job control resources and terminates running jobs void job_teardown(void) { // 20 tries will give processes about 1 sec to exit cleanly uint32_t remaining_tries = 20; bool all_dead = true; int i; Job *job; // Politely ask each job to terminate for (i = 0; i < MAX_RUNNING_JOBS; i++) { if ((job = table[i]) != NULL) { all_dead = false; uv_process_kill(&job->proc, SIGTERM); } } if (all_dead) { return; } os_delay(10, 0); // Right now any exited process are zombies waiting for us to acknowledge // their status with `wait` or handling SIGCHLD. libuv does that // automatically (and then calls `exit_cb`) but we have to give it a chance // by running the loop one more time event_poll(0); // Prepare to start shooting for (i = 0; i < MAX_RUNNING_JOBS; i++) { job = table[i]; // Still alive while (job && is_alive(job) && remaining_tries--) { os_delay(50, 0); // Acknowledge child exits event_poll(0); // It's possible that the event_poll call removed the job from the table, // reset 'job' so the next iteration won't run in that case. job = table[i]; } if (job && is_alive(job)) { uv_process_kill(&job->proc, SIGKILL); } } // Last run to ensure all children were removed event_poll(0); }
static int luv_process_kill(lua_State* L) { uv_process_t* handle = luv_check_process(L, 1); int signum = luv_parse_signal(L, 2); int ret = uv_process_kill(handle, signum); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, ret); return 1; }
void job_teardown() { // 20 tries will give processes about 1 sec to exit cleanly uint32_t remaining_tries = 20; bool all_dead = true; int i; Job *job; // Politely ask each job to terminate for (i = 0; i < MAX_RUNNING_JOBS; i++) { if ((job = table[i]) != NULL) { all_dead = false; uv_process_kill(&job->proc, SIGTERM); } } if (all_dead) { return; } os_delay(10, 0); // Right now any exited process are zombies waiting for us to acknowledge // their status with `wait` or handling SIGCHLD. libuv does that // automatically (and then calls `exit_cb`) but we have to give it a chance // by running the loop one more time uv_run(uv_default_loop(), UV_RUN_NOWAIT); // Prepare to start shooting for (i = 0; i < MAX_RUNNING_JOBS; i++) { if ((job = table[i]) == NULL) { continue; } // Still alive while (is_alive(job) && remaining_tries--) { os_delay(50, 0); // Acknowledge child exits uv_run(uv_default_loop(), UV_RUN_NOWAIT); } if (is_alive(job)) { uv_process_kill(&job->proc, SIGKILL); } } }
/// Iterates the table, sending SIGTERM to stopped jobs and SIGKILL to those /// that didn't die from SIGTERM after a while(exit_timeout is 0). static void job_prepare_cb(uv_prepare_t *handle) { Job *job; int i; for (i = 0; i < MAX_RUNNING_JOBS; i++) { if ((job = table[i]) == NULL || !job->stopped) { continue; } if ((job->exit_timeout--) == EXIT_TIMEOUT) { // Job was just stopped, close all stdio handles and send SIGTERM uv_process_kill(&job->proc, SIGTERM); } else if (job->exit_timeout == 0) { // We've waited long enough, send SIGKILL uv_process_kill(&job->proc, SIGKILL); } } }
static int lluv_process_kill(lua_State *L){ lluv_handle_t *handle = lluv_check_process(L, 1, LLUV_FLAG_OPEN); int sig = luaL_optint(L, 2, SIGTERM); int err = uv_process_kill(LLUV_H(handle, uv_process_t), sig); if(err < 0){ return lluv_fail(L, handle->flags, LLUV_ERR_UV, (uv_errno_t)err, NULL); } lua_settop(L, 1); return 1; }
// Kills the process with the specified signal. The user must still call close // on the process. int luv_process_kill(lua_State* L) { uv_process_t* handle = (uv_process_t*)luv_checkudata(L, 1, "process"); int signum = luaL_checkint(L, 2); if (uv_process_kill(handle, signum)) { uv_err_t err = uv_last_error(uv_default_loop()); return luaL_error(L, "process_kill: %s", uv_strerror(err)); } return 0; }
static int luv_process_kill(lua_State* L) { luv_object_t* self = (luv_object_t*)luaL_checkudata(L, 1, LUV_PROCESS_T); int signum = luaL_checkint(L, 2); if (uv_process_kill(&self->h.process, signum)) { uv_err_t err = uv_last_error(luvL_event_loop(L)); return luaL_error(L, uv_strerror(err)); } return 0; }
void SysProcess::kill() { uv_process_kill( &this->child_req , 1 ); #ifdef _WIN32 //TerminateProcess( this->pi_.hProcess, -1 ); #else pclose( p_stream ); #endif // _WIN32 }
static PyObject * Process_func_kill(Process *self, PyObject *args) { int signum, err; RAISE_IF_HANDLE_NOT_INITIALIZED(self, NULL); RAISE_IF_HANDLE_CLOSED(self, PyExc_HandleClosedError, NULL); if (!PyArg_ParseTuple(args, "i:kill", &signum)) { return NULL; } err = uv_process_kill(&self->process_h, signum); if (err < 0) { RAISE_UV_EXCEPTION(err, PyExc_ProcessError); return NULL; } Py_RETURN_NONE; }
static void timer_cb(uv_timer_t* handle) { uv_process_kill(&process, /* SIGTERM */ 15); uv_close((uv_handle_t*)handle, close_cb); }
int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg) { uv_stdio_container_t proc_stdio[3]; uv_process_options_t proc_opts; uv_process_t proc; uv_pipe_t proc_stdin, proc_stdout; uv_write_t write_req; int expected_exits = 1; ProcessData pdata = { .reading = false, .exited = 0, .old_mode = cur_tmode, .old_state = State, .shell_stdin = (uv_stream_t *)&proc_stdin, .wbuffer = NULL, }; out_flush(); if (opts & kShellOptCooked) { // set to normal mode settmode(TMODE_COOK); } // While the child is running, ignore terminating signals signal_reject_deadly(); // Create argv for `uv_spawn` // TODO(tarruda): we can use a static buffer for small argument vectors. 1024 // bytes should be enough for most of the commands and if more is necessary // we can allocate a another buffer proc_opts.args = shell_build_argv(cmd, extra_shell_arg); proc_opts.file = proc_opts.args[0]; proc_opts.exit_cb = exit_cb; // Initialize libuv structures proc_opts.stdio = proc_stdio; proc_opts.stdio_count = 3; // Hide window on Windows :) proc_opts.flags = UV_PROCESS_WINDOWS_HIDE; proc_opts.cwd = NULL; proc_opts.env = NULL; // The default is to inherit all standard file descriptors(this will change // when the UI is moved to an external process) proc_stdio[0].flags = UV_INHERIT_FD; proc_stdio[0].data.fd = 0; proc_stdio[1].flags = UV_INHERIT_FD; proc_stdio[1].data.fd = 1; proc_stdio[2].flags = UV_INHERIT_FD; proc_stdio[2].data.fd = 2; if (opts & (kShellOptHideMess | kShellOptExpand)) { // Ignore the shell stdio(redirects to /dev/null on unixes) proc_stdio[0].flags = UV_IGNORE; proc_stdio[1].flags = UV_IGNORE; proc_stdio[2].flags = UV_IGNORE; } else { State = EXTERNCMD; if (opts & kShellOptWrite) { // Write from the current buffer into the process stdin uv_pipe_init(uv_default_loop(), &proc_stdin, 0); write_req.data = &pdata; proc_stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; proc_stdio[0].data.stream = (uv_stream_t *)&proc_stdin; } if (opts & kShellOptRead) { // Read from the process stdout into the current buffer uv_pipe_init(uv_default_loop(), &proc_stdout, 0); proc_stdout.data = &pdata; proc_stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; proc_stdio[1].data.stream = (uv_stream_t *)&proc_stdout; ga_init(&pdata.ga, 1, BUFFER_LENGTH); } } if (uv_spawn(uv_default_loop(), &proc, &proc_opts)) { // Failed, probably due to `sh` not being executable if (!emsg_silent) { MSG_PUTS(_("\nCannot execute shell ")); msg_outtrans(p_sh); msg_putchar('\n'); } return proc_cleanup_exit(&pdata, &proc_opts, opts); } // Assign the flag address after `proc` is initialized by `uv_spawn` proc.data = &pdata; if (opts & kShellOptWrite) { // Queue everything for writing to the shell stdin write_selection(&write_req); expected_exits++; } if (opts & kShellOptRead) { // Start the read stream for the shell stdout uv_read_start((uv_stream_t *)&proc_stdout, alloc_cb, read_cb); expected_exits++; } // Keep running the loop until all three handles are completely closed while (pdata.exited < expected_exits) { uv_run(uv_default_loop(), UV_RUN_ONCE); if (got_int) { // Forward SIGINT to the shell // TODO(tarruda): for now this is only needed if the terminal is in raw // mode, but when the UI is externalized we'll also need it, so leave it // here uv_process_kill(&proc, SIGINT); got_int = false; } } if (opts & kShellOptRead) { if (pdata.ga.ga_len > 0) { // If there's an unfinished line in the growable array, append it now. append_ga_line(&pdata.ga); // remember that the NL was missing curbuf->b_no_eol_lnum = curwin->w_cursor.lnum; } else { curbuf->b_no_eol_lnum = 0; } ga_clear(&pdata.ga); } if (opts & kShellOptWrite) { free(pdata.wbuffer); } return proc_cleanup_exit(&pdata, &proc_opts, opts); } static int tokenize(char_u *str, char **argv) { int argc = 0, len; char_u *p = str; while (*p != NUL) { len = word_length(p); if (argv != NULL) { // Fill the slot argv[argc] = xmalloc(len + 1); memcpy(argv[argc], p, len); argv[argc][len] = NUL; } argc++; p += len; p = skipwhite(p); } return argc; }
void forza__kill() { if (child != NULL) { printf("killing child...\n"); uv_process_kill(child, SIGKILL); } }
static bool is_alive(Job *job) { return uv_process_kill(&job->proc, 0) == 0; }
extern "C" int rust_uv_process_kill(uv_process_t *p, int signum) { return uv_process_kill(p, signum); }