/// Terminates a job. This is a non-blocking operation, but if the job exists /// it's guaranteed to succeed(SIGKILL will eventually be sent) /// /// @param job The Job instance void job_stop(Job *job) { if (job->stopped_time) { return; } job->stopped_time = os_hrtime(); if (job->opts.pty) { // close all streams for pty jobs to send SIGHUP to the process job_close_streams(job); pty_process_close_master(job); } else { // Close the job's stdin. If the job doesn't close its own stdout/stderr, // they will be closed when the job exits(possibly due to being terminated // after a timeout) close_job_in(job); } if (!stop_requests++) { // When there's at least one stop request pending, start a timer that // will periodically check if a signal should be send to a to the job DLOG("Starting job kill timer"); uv_timer_start(&job_stop_timer, job_stop_timer_cb, 100, 100); } }
static void close_cb(uv_handle_t *handle) { Job *job = handle_get_job(handle); if (handle == (uv_handle_t *)&job->proc) { // Make sure all streams are properly closed to trigger callback invocation // when job->proc is closed close_job_in(job); close_job_out(job); close_job_err(job); } if (--job->refcount == 0) { // Invoke the exit_cb job_exit_callback(job); // Free all memory allocated for the job free(job->proc.data); free(job->proc_stdin.data); free(job->proc_stdout.data); free(job->proc_stderr.data); shell_free_argv(job->proc_opts.args); free(job); } }
void job_close_streams(Job *job) { close_job_in(job); close_job_out(job); close_job_err(job); }