]> granicus.if.org Git - vim/commitdiff
patch 8.0.0045 v8.0.0045
authorBram Moolenaar <Bram@vim.org>
Tue, 18 Oct 2016 14:27:23 +0000 (16:27 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 18 Oct 2016 14:27:23 +0000 (16:27 +0200)
Problem:    Calling job_stop() right after job_start() does not work.
Solution:   Block signals while fork is still busy. (Ozaki Kiichi, closes
            #1155)

src/auto/configure
src/config.h.in
src/configure.in
src/os_unix.c
src/testdir/test_channel.vim
src/version.c

index b42f601db2ff6b9d36715654eadd7f1073e39c84..27aea9c989bf4369cddf7fcd99c816acbf876203 100755 (executable)
@@ -12004,7 +12004,7 @@ for ac_func in bcmp fchdir fchown fsync getcwd getpseudotty \
        getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \
        memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
        setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
-       sigvec strcasecmp strerror strftime stricmp strncasecmp \
+       sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
        strnicmp strpbrk strtol tgetent towlower towupper iswupper \
        usleep utime utimes
 do :
index 9d35e48fa6c9b201f16680ed19be383520dfa59a..62427e28eb511033122584dc40d87946e52ba325 100644 (file)
 #undef HAVE_SIGSET
 #undef HAVE_SIGSETJMP
 #undef HAVE_SIGSTACK
+#undef HAVE_SIGPROCMASK
 #undef HAVE_SIGVEC
 #undef HAVE_SMACK
 #undef HAVE_STRCASECMP
index c0a60b227717fed4591e68a6def90907ad6953bf..43bf9ad17037a9d920a6cf0e152ae2bd45e6c8f9 100644 (file)
@@ -3598,7 +3598,7 @@ AC_CHECK_FUNCS(bcmp fchdir fchown fsync getcwd getpseudotty \
        getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \
        memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
        setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
-       sigvec strcasecmp strerror strftime stricmp strncasecmp \
+       sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
        strnicmp strpbrk strtol tgetent towlower towupper iswupper \
        usleep utime utimes)
 AC_FUNC_FSEEKO
index bc9acd4f7b1b6a628fda43a28f9acc3b76a3a93c..05691841392794e1b139d01df09987fc29986fdd 100644 (file)
@@ -211,6 +211,15 @@ static RETSIGTYPE deathtrap SIGPROTOARG;
 static void catch_int_signal(void);
 static void set_signals(void);
 static void catch_signals(RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)());
+#ifdef HAVE_SIGPROCMASK
+# define SIGSET_DECL(set)      sigset_t set;
+# define BLOCK_SIGNALS(set)    block_signals(set)
+# define UNBLOCK_SIGNALS(set)  unblock_signals(set)
+#else
+# define SIGSET_DECL(set)
+# define BLOCK_SIGNALS(set)    do { /**/ } while (0)
+# define UNBLOCK_SIGNALS(set)  do { /**/ } while (0)
+#endif
 static int  have_wildcard(int, char_u **);
 static int  have_dollars(int, char_u **);
 
@@ -1468,6 +1477,33 @@ catch_signals(
            signal(signal_info[i].sig, func_other);
 }
 
+#ifdef HAVE_SIGPROCMASK
+    static void
+block_signals(sigset_t *set)
+{
+    sigset_t   newset;
+    int                i;
+
+    sigemptyset(&newset);
+
+    for (i = 0; signal_info[i].sig != -1; i++)
+       sigaddset(&newset, signal_info[i].sig);
+
+# if defined(_REENTRANT) && defined(SIGCONT)
+    /* SIGCONT isn't in the list, because its default action is ignore */
+    sigaddset(&newset, SIGCONT);
+# endif
+
+    sigprocmask(SIG_BLOCK, &newset, set);
+}
+
+    static void
+unblock_signals(sigset_t *set)
+{
+    sigprocmask(SIG_SETMASK, set, NULL);
+}
+#endif
+
 /*
  * Handling of SIGHUP, SIGQUIT and SIGTERM:
  * "when" == a signal:       when busy, postpone and return FALSE, otherwise
@@ -4283,12 +4319,18 @@ mch_call_shell(
 
     if (!pipe_error)                   /* pty or pipe opened or not used */
     {
+       SIGSET_DECL(curset)
+
 # ifdef __BEOS__
        beos_cleanup_read_thread();
 # endif
 
-       if ((pid = fork()) == -1)       /* maybe we should use vfork() */
+       BLOCK_SIGNALS(&curset);
+       pid = fork();   /* maybe we should use vfork() */
+       if (pid == -1)
        {
+           UNBLOCK_SIGNALS(&curset);
+
            MSG_PUTS(_("\nCannot fork\n"));
            if ((options & (SHELL_READ|SHELL_WRITE))
 # ifdef FEAT_GUI
@@ -4315,6 +4357,7 @@ mch_call_shell(
        else if (pid == 0)      /* child */
        {
            reset_signals();            /* handle signals normally */
+           UNBLOCK_SIGNALS(&curset);
 
            if (!show_shell_mess || (options & SHELL_EXPAND))
            {
@@ -4458,6 +4501,7 @@ mch_call_shell(
             */
            catch_signals(SIG_IGN, SIG_ERR);
            catch_int_signal();
+           UNBLOCK_SIGNALS(&curset);
 
            /*
             * For the GUI we redirect stdin, stdout and stderr to our window.
@@ -5069,6 +5113,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
     int                use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE;
     int                use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE;
     int                use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
+    SIGSET_DECL(curset)
 
     if (use_out_for_err && use_null_for_out)
        use_null_for_err = TRUE;
@@ -5140,13 +5185,14 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
            goto failed;
     }
 
+    BLOCK_SIGNALS(&curset);
     pid = fork();      /* maybe we should use vfork() */
-    if (pid  == -1)
+    if (pid == -1)
     {
        /* failed to fork */
+       UNBLOCK_SIGNALS(&curset);
        goto failed;
     }
-
     if (pid == 0)
     {
        int     null_fd = -1;
@@ -5154,6 +5200,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
 
        /* child */
        reset_signals();                /* handle signals normally */
+       UNBLOCK_SIGNALS(&curset);
 
 # ifdef HAVE_SETSID
        /* Create our own process group, so that the child and all its
@@ -5234,6 +5281,8 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
     }
 
     /* parent */
+    UNBLOCK_SIGNALS(&curset);
+
     job->jv_pid = pid;
     job->jv_status = JOB_STARTED;
     job->jv_channel = channel;  /* ch_refcount was set above */
@@ -5357,7 +5406,6 @@ mch_detect_ended_job(job_T *job_list)
        }
     }
     return NULL;
-
 }
 
     int
index e7ba6676801991fbe8ee904e5d0c4c77def12b5b..0a50ed47e458b83459ea11b2c9225b9b761bce33 100644 (file)
@@ -1433,6 +1433,21 @@ func Test_job_start_invalid()
   call assert_fails('call job_start("")', 'E474:')
 endfunc
 
+func Test_job_stop_immediately()
+  if !has('job')
+    return
+  endif
+
+  let job = job_start([s:python, '-c', 'import time;time.sleep(10)'])
+  try
+    call job_stop(job)
+    call WaitFor('"dead" == job_status(job)')
+    call assert_equal('dead', job_status(job))
+  finally
+    call job_stop(job, 'kill')
+  endtry
+endfunc
+
 " This was leaking memory.
 func Test_partial_in_channel_cycle()
   let d = {}
index 80a837a381264d23e01e4cb3ca663e8de26770ba..b15752024a9b60d38c34415e47c2b6acfdbc5010 100644 (file)
@@ -764,6 +764,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    45,
 /**/
     44,
 /**/