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 #3786)
diff --git a/src/channel.c b/src/channel.c
index cf68271..20cf462 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -5152,6 +5152,9 @@
     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 @@
     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
index c616e06..a17abe3 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -5655,6 +5655,23 @@
 	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 @@
     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 @@
 		/* 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
index 459103d..ddc56bc 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1550,7 +1550,10 @@
     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
index f81701a..2aef3e1 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -2002,3 +2002,27 @@
     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
index 1b4eef9..05b18ed 100644
--- a/src/version.c
+++ b/src/version.c
@@ -784,6 +784,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    863,
+/**/
     862,
 /**/
     861,