channels: reflect exit due to signals in exit status code (#10573)
Uses `128 + term_signal` in case of exit due to a signal. Fixes https://github.com/neovim/neovim/issues/10571.
This commit is contained in:
parent
fa0c677a63
commit
939d9053bd
|
@ -67,7 +67,7 @@ For |on_stdout| and |on_stderr| see |channel-callback|.
|
|||
*on_exit*
|
||||
Arguments passed to on_exit callback:
|
||||
0: |job-id|
|
||||
1: Exit-code of the process.
|
||||
1: Exit-code of the process, or 128+SIGNUM if by signal (e.g. 143 on SIGTERM).
|
||||
2: Event type: "exit"
|
||||
|
||||
|
||||
|
|
|
@ -12354,7 +12354,6 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
Channel *data = find_job(argvars[0].vval.v_number, true);
|
||||
if (!data) {
|
||||
return;
|
||||
|
|
|
@ -101,6 +101,10 @@ static void close_cb(uv_handle_t *handle)
|
|||
static void exit_cb(uv_process_t *handle, int64_t status, int term_signal)
|
||||
{
|
||||
Process *proc = handle->data;
|
||||
proc->status = (int)status;
|
||||
#if defined(WIN32)
|
||||
// Use stored/expected signal.
|
||||
term_signal = proc->exit_signal;
|
||||
#endif
|
||||
proc->status = term_signal ? 128 + term_signal : (int)status;
|
||||
proc->internal_exit_cb(proc);
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ void process_close_streams(Process *proc) FUNC_ATTR_NONNULL_ALL
|
|||
/// 0 for no wait. -1 to wait until the process quits.
|
||||
/// @return Exit code of the process. proc->status will have the same value.
|
||||
/// -1 if the timeout expired while the process is still running.
|
||||
/// -2 if the user interruped the wait.
|
||||
/// -2 if the user interrupted the wait.
|
||||
int process_wait(Process *proc, int ms, MultiQueue *events)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
|
@ -220,6 +220,7 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL
|
|||
return;
|
||||
}
|
||||
proc->stopped_time = os_hrtime();
|
||||
proc->exit_signal = SIGTERM;
|
||||
|
||||
switch (proc->type) {
|
||||
case kProcessTypeUv:
|
||||
|
@ -253,8 +254,10 @@ static void children_kill_cb(uv_timer_t *handle)
|
|||
}
|
||||
uint64_t term_sent = UINT64_MAX == proc->stopped_time;
|
||||
if (kProcessTypePty != proc->type || term_sent) {
|
||||
proc->exit_signal = SIGKILL;
|
||||
os_proc_tree_kill(proc->pid, SIGKILL);
|
||||
} else {
|
||||
proc->exit_signal = SIGTERM;
|
||||
os_proc_tree_kill(proc->pid, SIGTERM);
|
||||
proc->stopped_time = UINT64_MAX; // Flag: SIGTERM was sent.
|
||||
// Restart timer.
|
||||
|
@ -403,4 +406,3 @@ static void on_process_stream_close(Stream *stream, void *data)
|
|||
Process *proc = data;
|
||||
decref(proc);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ struct process {
|
|||
Loop *loop;
|
||||
void *data;
|
||||
int pid, status, refcount;
|
||||
uint8_t exit_signal; // Signal used when killing (on Windows).
|
||||
uint64_t stopped_time; // process_stop() timestamp
|
||||
const char *cwd;
|
||||
char **argv;
|
||||
|
|
|
@ -288,7 +288,7 @@ static void chld_handler(uv_signal_t *handle, int signum)
|
|||
if (WIFEXITED(stat)) {
|
||||
proc->status = WEXITSTATUS(stat);
|
||||
} else if (WIFSIGNALED(stat)) {
|
||||
proc->status = WTERMSIG(stat);
|
||||
proc->status = 128 + WTERMSIG(stat);
|
||||
}
|
||||
proc->internal_exit_cb(proc);
|
||||
}
|
||||
|
|
|
@ -252,7 +252,7 @@ static void pty_process_finish2(PtyProcess *ptyproc)
|
|||
|
||||
DWORD exit_code = 0;
|
||||
GetExitCodeProcess(ptyproc->process_handle, &exit_code);
|
||||
proc->status = (int)exit_code;
|
||||
proc->status = proc->exit_signal ? 128 + proc->exit_signal : (int)exit_code;
|
||||
|
||||
CloseHandle(ptyproc->process_handle);
|
||||
ptyproc->process_handle = NULL;
|
||||
|
|
|
@ -183,7 +183,7 @@ describe('jobs', function()
|
|||
)
|
||||
nvim('command', "call jobstop(j)")
|
||||
eq({'notification', 'stdout', {0, {''}}}, next_msg())
|
||||
eq({'notification', 'exit', {0, iswin() and 15 or 0}}, next_msg())
|
||||
eq({'notification', 'exit', {0, 143}}, next_msg())
|
||||
end)
|
||||
|
||||
it('preserves NULs', function()
|
||||
|
@ -217,7 +217,7 @@ describe('jobs', function()
|
|||
eq({'notification', 'stdout', {0, {'abc', 'xyz'}}}, next_msg())
|
||||
nvim('command', "call jobstop(j)")
|
||||
eq({'notification', 'stdout', {0, {''}}}, next_msg())
|
||||
eq({'notification', 'exit', {0, iswin() and 15 or 0}}, next_msg())
|
||||
eq({'notification', 'exit', {0, 143}}, next_msg())
|
||||
end)
|
||||
|
||||
it('preserves newlines', function()
|
||||
|
@ -234,7 +234,7 @@ describe('jobs', function()
|
|||
next_msg())
|
||||
nvim('command', "call jobstop(j)")
|
||||
eq({'notification', 'stdout', {0, {''}}}, next_msg())
|
||||
eq({'notification', 'exit', {0, iswin() and 15 or 0}}, next_msg())
|
||||
eq({'notification', 'exit', {0, 143}}, next_msg())
|
||||
end)
|
||||
|
||||
it('avoids sending final newline', function()
|
||||
|
@ -244,7 +244,7 @@ describe('jobs', function()
|
|||
next_msg())
|
||||
nvim('command', "call jobstop(j)")
|
||||
eq({'notification', 'stdout', {0, {''}}}, next_msg())
|
||||
eq({'notification', 'exit', {0, iswin() and 15 or 0}}, next_msg())
|
||||
eq({'notification', 'exit', {0, 143}}, next_msg())
|
||||
end)
|
||||
|
||||
it('closes the job streams with jobclose', function()
|
||||
|
@ -284,18 +284,7 @@ describe('jobs', function()
|
|||
neq(NIL, meths.get_proc(pid))
|
||||
nvim('command', 'call jobstop(j)')
|
||||
eq({'notification', 'stdout', {0, {''}}}, next_msg())
|
||||
if iswin() then
|
||||
expect_msg_seq(
|
||||
-- win64
|
||||
{ {'notification', 'exit', {0, 1}}
|
||||
},
|
||||
-- win32
|
||||
{ {'notification', 'exit', {0, 15}}
|
||||
}
|
||||
)
|
||||
else
|
||||
eq({'notification', 'exit', {0, 0}}, next_msg())
|
||||
end
|
||||
eq({'notification', 'exit', {0, 143}}, next_msg())
|
||||
eq(NIL, meths.get_proc(pid))
|
||||
end)
|
||||
|
||||
|
|
Loading…
Reference in New Issue