0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

patch 8.0.0045

Problem:    Calling job_stop() right after job_start() does not work.
Solution:   Block signals while fork is still busy. (Ozaki Kiichi, closes
            #1155)
This commit is contained in:
Bram Moolenaar
2016-10-18 16:27:23 +02:00
parent 025e3e0baf
commit bb09ceb954
6 changed files with 72 additions and 6 deletions

2
src/auto/configure vendored
View File

@@ -12004,7 +12004,7 @@ for ac_func in bcmp fchdir fchown fsync getcwd getpseudotty \
getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \ getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \ memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \ 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 \ strnicmp strpbrk strtol tgetent towlower towupper iswupper \
usleep utime utimes usleep utime utimes
do : do :

View File

@@ -190,6 +190,7 @@
#undef HAVE_SIGSET #undef HAVE_SIGSET
#undef HAVE_SIGSETJMP #undef HAVE_SIGSETJMP
#undef HAVE_SIGSTACK #undef HAVE_SIGSTACK
#undef HAVE_SIGPROCMASK
#undef HAVE_SIGVEC #undef HAVE_SIGVEC
#undef HAVE_SMACK #undef HAVE_SMACK
#undef HAVE_STRCASECMP #undef HAVE_STRCASECMP

View File

@@ -3598,7 +3598,7 @@ AC_CHECK_FUNCS(bcmp fchdir fchown fsync getcwd getpseudotty \
getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \ getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \ memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \ 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 \ strnicmp strpbrk strtol tgetent towlower towupper iswupper \
usleep utime utimes) usleep utime utimes)
AC_FUNC_FSEEKO AC_FUNC_FSEEKO

View File

@@ -211,6 +211,15 @@ static RETSIGTYPE deathtrap SIGPROTOARG;
static void catch_int_signal(void); static void catch_int_signal(void);
static void set_signals(void); static void set_signals(void);
static void catch_signals(RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()); 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_wildcard(int, char_u **);
static int have_dollars(int, char_u **); static int have_dollars(int, char_u **);
@@ -1468,6 +1477,33 @@ catch_signals(
signal(signal_info[i].sig, func_other); 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: * Handling of SIGHUP, SIGQUIT and SIGTERM:
* "when" == a signal: when busy, postpone and return FALSE, otherwise * "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 */ if (!pipe_error) /* pty or pipe opened or not used */
{ {
SIGSET_DECL(curset)
# ifdef __BEOS__ # ifdef __BEOS__
beos_cleanup_read_thread(); beos_cleanup_read_thread();
# endif # 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")); MSG_PUTS(_("\nCannot fork\n"));
if ((options & (SHELL_READ|SHELL_WRITE)) if ((options & (SHELL_READ|SHELL_WRITE))
# ifdef FEAT_GUI # ifdef FEAT_GUI
@@ -4315,6 +4357,7 @@ mch_call_shell(
else if (pid == 0) /* child */ else if (pid == 0) /* child */
{ {
reset_signals(); /* handle signals normally */ reset_signals(); /* handle signals normally */
UNBLOCK_SIGNALS(&curset);
if (!show_shell_mess || (options & SHELL_EXPAND)) if (!show_shell_mess || (options & SHELL_EXPAND))
{ {
@@ -4458,6 +4501,7 @@ mch_call_shell(
*/ */
catch_signals(SIG_IGN, SIG_ERR); catch_signals(SIG_IGN, SIG_ERR);
catch_int_signal(); catch_int_signal();
UNBLOCK_SIGNALS(&curset);
/* /*
* For the GUI we redirect stdin, stdout and stderr to our window. * 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_out = options->jo_io[PART_OUT] == JIO_FILE;
int use_file_for_err = options->jo_io[PART_ERR] == 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; int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
SIGSET_DECL(curset)
if (use_out_for_err && use_null_for_out) if (use_out_for_err && use_null_for_out)
use_null_for_err = TRUE; use_null_for_err = TRUE;
@@ -5140,13 +5185,14 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
goto failed; goto failed;
} }
BLOCK_SIGNALS(&curset);
pid = fork(); /* maybe we should use vfork() */ pid = fork(); /* maybe we should use vfork() */
if (pid == -1) if (pid == -1)
{ {
/* failed to fork */ /* failed to fork */
UNBLOCK_SIGNALS(&curset);
goto failed; goto failed;
} }
if (pid == 0) if (pid == 0)
{ {
int null_fd = -1; int null_fd = -1;
@@ -5154,6 +5200,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
/* child */ /* child */
reset_signals(); /* handle signals normally */ reset_signals(); /* handle signals normally */
UNBLOCK_SIGNALS(&curset);
# ifdef HAVE_SETSID # ifdef HAVE_SETSID
/* Create our own process group, so that the child and all its /* 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 */ /* parent */
UNBLOCK_SIGNALS(&curset);
job->jv_pid = pid; job->jv_pid = pid;
job->jv_status = JOB_STARTED; job->jv_status = JOB_STARTED;
job->jv_channel = channel; /* ch_refcount was set above */ job->jv_channel = channel; /* ch_refcount was set above */
@@ -5357,7 +5406,6 @@ mch_detect_ended_job(job_T *job_list)
} }
} }
return NULL; return NULL;
} }
int int

View File

@@ -1433,6 +1433,21 @@ func Test_job_start_invalid()
call assert_fails('call job_start("")', 'E474:') call assert_fails('call job_start("")', 'E474:')
endfunc 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. " This was leaking memory.
func Test_partial_in_channel_cycle() func Test_partial_in_channel_cycle()
let d = {} let d = {}

View File

@@ -764,6 +764,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
45,
/**/ /**/
44, 44,
/**/ /**/