/// 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); } }
void queue_process_events(Queue *queue, int ms) { int remaining = ms; uint64_t before = (remaining > 0) ? os_hrtime() : 0; while (!queue_empty(queue)) { if (remaining > 0) { Event e = queue_pop(queue); if (e.handler) { e.handler(e.argv); } uint64_t now = os_hrtime(); remaining -= (int) ((now - before) / 1000000); if (remaining <= 0) { break; } } } }
static uint8_t check_multiclick(int code, int grid, int row, int col) { static int orig_num_clicks = 0; static int orig_mouse_code = 0; static int orig_mouse_grid = 0; static int orig_mouse_col = 0; static int orig_mouse_row = 0; static uint64_t orig_mouse_time = 0; // time of previous mouse click if (code == KE_LEFTRELEASE || code == KE_RIGHTRELEASE || code == KE_MIDDLERELEASE) { return 0; } uint64_t mouse_time = os_hrtime(); // time of current mouse click (ns) // compute the time elapsed since the previous mouse click and // convert p_mouse from ms to ns uint64_t timediff = mouse_time - orig_mouse_time; uint64_t mouset = (uint64_t)p_mouset * 1000000; if (code == orig_mouse_code && timediff < mouset && orig_num_clicks != 4 && orig_mouse_grid == grid && orig_mouse_col == col && orig_mouse_row == row) { orig_num_clicks++; } else { orig_num_clicks = 1; } orig_mouse_code = code; orig_mouse_grid = grid; orig_mouse_col = col; orig_mouse_row = row; orig_mouse_time = mouse_time; uint8_t modifiers = 0; if (orig_num_clicks == 2) { modifiers |= MOD_MASK_2CLICK; } else if (orig_num_clicks == 3) { modifiers |= MOD_MASK_3CLICK; } else if (orig_num_clicks == 4) { modifiers |= MOD_MASK_4CLICK; } return modifiers; }
/// 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_stop_timer_cb(uv_timer_t *handle) { Job *job; uint64_t now = os_hrtime(); for (size_t i = 0; i < MAX_RUNNING_JOBS; i++) { if ((job = table[i]) == NULL || !job->stopped_time) { continue; } uint64_t elapsed = now - job->stopped_time; if (!job->term_sent && elapsed >= TERM_TIMEOUT) { ILOG("Sending SIGTERM to job(id: %d)", job->id); uv_kill(job->pid, SIGTERM); job->term_sent = true; } else if (elapsed >= KILL_TIMEOUT) { ILOG("Sending SIGKILL to job(id: %d)", job->id); uv_kill(job->pid, SIGKILL); process_close(job); } } }
// Mouse event handling code(Extract row/col if available and detect multiple // clicks) static unsigned int handle_mouse_event(char **ptr, uint8_t *buf, unsigned int bufsize) { int mouse_code = 0; int type = 0; if (bufsize == 3) { mouse_code = buf[2]; type = buf[1]; } else if (bufsize == 6) { // prefixed with K_SPECIAL KS_MODIFIER mod mouse_code = buf[5]; type = buf[4]; } if (type != KS_EXTRA || !((mouse_code >= KE_LEFTMOUSE && mouse_code <= KE_RIGHTRELEASE) || (mouse_code >= KE_MOUSEDOWN && mouse_code <= KE_MOUSERIGHT))) { return bufsize; } // a <[COL],[ROW]> sequence can follow and will set the mouse_row/mouse_col // global variables. This is ugly but its how the rest of the code expects to // find mouse coordinates, and it would be too expensive to refactor this // now. int col, row, advance; if (sscanf(*ptr, "<%d,%d>%n", &col, &row, &advance) != EOF && advance) { if (col >= 0 && row >= 0) { mouse_row = row; mouse_col = col; } *ptr += advance; } static int orig_num_clicks = 0; static int orig_mouse_code = 0; static int orig_mouse_col = 0; static int orig_mouse_row = 0; static uint64_t orig_mouse_time = 0; // time of previous mouse click uint64_t mouse_time = os_hrtime(); // time of current mouse click // compute the time elapsed since the previous mouse click and // convert p_mouse from ms to ns uint64_t timediff = mouse_time - orig_mouse_time; uint64_t mouset = (uint64_t)p_mouset * 1000000; if (mouse_code == orig_mouse_code && timediff < mouset && orig_num_clicks != 4 && orig_mouse_col == mouse_col && orig_mouse_row == mouse_row) { orig_num_clicks++; } else { orig_num_clicks = 1; } orig_mouse_code = mouse_code; orig_mouse_col = mouse_col; orig_mouse_row = mouse_row; orig_mouse_time = mouse_time; uint8_t modifiers = 0; if (orig_num_clicks == 2) { modifiers |= MOD_MASK_2CLICK; } else if (orig_num_clicks == 3) { modifiers |= MOD_MASK_3CLICK; } else if (orig_num_clicks == 4) { modifiers |= MOD_MASK_4CLICK; } if (modifiers) { if (buf[1] != KS_MODIFIER) { // no modifiers in the buffer yet, shift the bytes 3 positions memcpy(buf + 3, buf, 3); // add the modifier sequence buf[0] = K_SPECIAL; buf[1] = KS_MODIFIER; buf[2] = modifiers; bufsize += 3; } else { buf[2] |= modifiers; } } return bufsize; }