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:
2
src/auto/configure
vendored
2
src/auto/configure
vendored
@@ -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 :
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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 = {}
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user