# HG changeset patch # User Bram Moolenaar # Date 1548946806 -3600 # Node ID 287104a1d51eb36b101ea21bbdac2c358784dfd9 # Parent 83f00bd3ddb036015ae84b0d94491615e9250bee patch 8.1.0863: cannot see what signal caused a job to end commit https://github.com/vim/vim/commit/b3051ce82f2e8af95ce3b6a41867f70aee5ecc82 Author: Bram Moolenaar Date: Thu Jan 31 15:52:11 2019 +0100 patch 8.1.0863: cannot see what signal caused a job to end Problem: Cannot see what signal caused a job to end. Solution: Add "termsig" to job_info(). (Ozaki Kiichi, closes https://github.com/vim/vim/issues/3786) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -5745,6 +5745,11 @@ job_info([{job}]) *job_info()* "exit_cb" function to be called on exit "stoponexit" |job-stoponexit| + Only in Unix: + "termsig" the signal which terminated the process + (See |job_stop()| for the values) + only valid when "status" is "dead" + Without any arguments, returns a List with all Job objects. job_setoptions({job}, {options}) *job_setoptions()* diff --git a/src/channel.c b/src/channel.c --- a/src/channel.c +++ b/src/channel.c @@ -5152,6 +5152,9 @@ job_free_contents(job_T *job) vim_free(job->jv_tty_in); vim_free(job->jv_tty_out); vim_free(job->jv_stoponexit); +#ifdef UNIX + vim_free(job->jv_termsig); +#endif free_callback(job->jv_exit_cb, job->jv_exit_partial); if (job->jv_argv != NULL) { @@ -5908,6 +5911,9 @@ job_info(job_T *job, dict_T *dict) dict_add_number(dict, "exitval", job->jv_exitval); dict_add_string(dict, "exit_cb", job->jv_exit_cb); dict_add_string(dict, "stoponexit", job->jv_stoponexit); +#ifdef UNIX + dict_add_string(dict, "termsig", job->jv_termsig); +#endif l = list_alloc(); if (l != NULL) diff --git a/src/os_unix.c b/src/os_unix.c --- a/src/os_unix.c +++ b/src/os_unix.c @@ -5655,6 +5655,23 @@ failed: close(pty_slave_fd); } + static char_u * +get_signal_name(int sig) +{ + int i; + char_u numbuf[NUMBUFLEN]; + + if (sig == SIGKILL) + return vim_strsave((char_u *)"kill"); + + for (i = 0; signal_info[i].sig != -1; i++) + if (sig == signal_info[i].sig) + return strlow_save((char_u *)signal_info[i].name); + + vim_snprintf((char *)numbuf, NUMBUFLEN, "%d", sig); + return vim_strsave(numbuf); +} + char * mch_job_status(job_T *job) { @@ -5691,8 +5708,10 @@ mch_job_status(job_T *job) if (WIFSIGNALED(status)) { job->jv_exitval = -1; - if (job->jv_status < JOB_ENDED) - ch_log(job->jv_channel, "Job terminated by a signal"); + job->jv_termsig = get_signal_name(WTERMSIG(status)); + if (job->jv_status < JOB_ENDED && job->jv_termsig != NULL) + ch_log(job->jv_channel, "Job terminated by signal \"%s\"", + job->jv_termsig); goto return_dead; } return "run"; @@ -5738,7 +5757,10 @@ mch_detect_ended_job(job_T *job_list) /* LINTED avoid "bitwise operation on signed value" */ job->jv_exitval = WEXITSTATUS(status); else if (WIFSIGNALED(status)) + { job->jv_exitval = -1; + job->jv_termsig = get_signal_name(WTERMSIG(status)); + } if (job->jv_status < JOB_ENDED) { ch_log(job->jv_channel, "Job ended"); diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -1550,7 +1550,10 @@ struct jobvar_S char_u *jv_tty_in; /* controlling tty input, allocated */ char_u *jv_tty_out; /* controlling tty output, allocated */ jobstatus_T jv_status; - char_u *jv_stoponexit; /* allocated */ + char_u *jv_stoponexit; /* allocated */ +#ifdef UNIX + char_u *jv_termsig; /* allocated */ +#endif int jv_exitval; char_u *jv_exit_cb; /* allocated */ partial_T *jv_exit_partial; diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -2002,3 +2002,27 @@ func Test_raw_large_data() unlet g:out endtry endfunc + +func Test_job_exitval_and_termsig() + if !has('unix') + return + endif + + " Terminate job normally + let cmd = ['echo'] + let job = job_start(cmd) + call WaitForAssert({-> assert_equal("dead", job_status(job))}) + let info = job_info(job) + call assert_equal(0, info.exitval) + call assert_equal("", info.termsig) + + " Terminate job by signal + let cmd = ['sleep', '10'] + let job = job_start(cmd) + sleep 10m + call job_stop(job) + call WaitForAssert({-> assert_equal("dead", job_status(job))}) + let info = job_info(job) + call assert_equal(-1, info.exitval) + call assert_equal("term", info.termsig) +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -784,6 +784,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 863, +/**/ 862, /**/ 861,