mirror of
https://github.com/neovim/neovim.git
synced 2025-09-12 14:28:18 +00:00
job: implement job_wait()
Used to wait synchronously for a job to end.
This commit is contained in:

committed by
Thiago de Arruda

parent
6af15f706a
commit
9f624f0937
@@ -14,6 +14,7 @@
|
|||||||
#include "nvim/os/event_defs.h"
|
#include "nvim/os/event_defs.h"
|
||||||
#include "nvim/os/time.h"
|
#include "nvim/os/time.h"
|
||||||
#include "nvim/os/shell.h"
|
#include "nvim/os/shell.h"
|
||||||
|
#include "nvim/os/signal.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/term.h"
|
#include "nvim/term.h"
|
||||||
@@ -25,6 +26,8 @@
|
|||||||
struct job {
|
struct job {
|
||||||
// Job id the index in the job table plus one.
|
// Job id the index in the job table plus one.
|
||||||
int id;
|
int id;
|
||||||
|
// Exit status code of the job process
|
||||||
|
int64_t status;
|
||||||
// Number of polls after a SIGTERM that will trigger a SIGKILL
|
// Number of polls after a SIGTERM that will trigger a SIGKILL
|
||||||
int exit_timeout;
|
int exit_timeout;
|
||||||
// exit_cb may be called while there's still pending data from stdout/stderr.
|
// exit_cb may be called while there's still pending data from stdout/stderr.
|
||||||
@@ -163,6 +166,7 @@ Job *job_start(char **argv,
|
|||||||
// Initialize
|
// Initialize
|
||||||
job->id = i + 1;
|
job->id = i + 1;
|
||||||
*status = job->id;
|
*status = job->id;
|
||||||
|
job->status = -1;
|
||||||
job->pending_refs = 3;
|
job->pending_refs = 3;
|
||||||
job->pending_closes = 4;
|
job->pending_closes = 4;
|
||||||
job->data = data;
|
job->data = data;
|
||||||
@@ -257,6 +261,64 @@ void job_stop(Job *job)
|
|||||||
job->stopped = true;
|
job->stopped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// job_wait - synchronously wait for a job to finish
|
||||||
|
///
|
||||||
|
/// @param job The job instance
|
||||||
|
/// @param ms Number of milliseconds to wait, 0 for not waiting, -1 for
|
||||||
|
/// waiting until the job quits.
|
||||||
|
/// @return returns the status code of the exited job. -1 if the job is
|
||||||
|
/// still running and the `timeout` has expired. Note that this is
|
||||||
|
/// indistinguishable from the process returning -1 by itself. Which
|
||||||
|
/// is possible on some OS.
|
||||||
|
int job_wait(Job *job, int ms) FUNC_ATTR_NONNULL_ALL
|
||||||
|
{
|
||||||
|
// switch to cooked so `got_int` will be set if the user interrupts
|
||||||
|
int old_mode = cur_tmode;
|
||||||
|
settmode(TMODE_COOK);
|
||||||
|
|
||||||
|
EventSource sources[] = {job_event_source(job), signal_event_source(), NULL};
|
||||||
|
|
||||||
|
// keep track of the elapsed time if ms > 0
|
||||||
|
uint64_t before = (ms > 0) ? os_hrtime() : 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// check if the job has exited (and the status is available).
|
||||||
|
if (job->pending_refs == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_poll(ms, sources);
|
||||||
|
|
||||||
|
// we'll assume that a user frantically hitting interrupt doesn't like
|
||||||
|
// the current job. Signal that it has to be killed.
|
||||||
|
if (got_int) {
|
||||||
|
job_stop(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ms == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the poll timed out, if not, decrease the ms to wait for the
|
||||||
|
// next run
|
||||||
|
if (ms > 0) {
|
||||||
|
uint64_t now = os_hrtime();
|
||||||
|
ms -= (int) ((now - before) / 1000000);
|
||||||
|
before = now;
|
||||||
|
|
||||||
|
// if the time elapsed is greater than the `ms` wait time, break
|
||||||
|
if (ms <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
settmode(old_mode);
|
||||||
|
|
||||||
|
// return -1 for a timeout, the job status otherwise
|
||||||
|
return (job->pending_refs) ? -1 : (int) job->status;
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes data to the job's stdin. This is a non-blocking operation, it
|
/// Writes data to the job's stdin. This is a non-blocking operation, it
|
||||||
/// returns when the write request was sent.
|
/// returns when the write request was sent.
|
||||||
///
|
///
|
||||||
@@ -377,6 +439,7 @@ static void exit_cb(uv_process_t *proc, int64_t status, int term_signal)
|
|||||||
{
|
{
|
||||||
Job *job = handle_get_job((uv_handle_t *)proc);
|
Job *job = handle_get_job((uv_handle_t *)proc);
|
||||||
|
|
||||||
|
job->status = status;
|
||||||
if (--job->pending_refs == 0) {
|
if (--job->pending_refs == 0) {
|
||||||
emit_exit_event(job);
|
emit_exit_event(job);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user