Skip to content

Commit bb09ceb

Browse files
committed
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)
1 parent 025e3e0 commit bb09ceb

File tree

6 files changed

+72
-6
lines changed

6 files changed

+72
-6
lines changed

src/auto/configure

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12004,7 +12004,7 @@ for ac_func in bcmp fchdir fchown fsync getcwd getpseudotty \
1200412004
getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \
1200512005
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
1200612006
setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
12007-
sigvec strcasecmp strerror strftime stricmp strncasecmp \
12007+
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
1200812008
strnicmp strpbrk strtol tgetent towlower towupper iswupper \
1200912009
usleep utime utimes
1201012010
do :

src/config.h.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@
190190
#undef HAVE_SIGSET
191191
#undef HAVE_SIGSETJMP
192192
#undef HAVE_SIGSTACK
193+
#undef HAVE_SIGPROCMASK
193194
#undef HAVE_SIGVEC
194195
#undef HAVE_SMACK
195196
#undef HAVE_STRCASECMP

src/configure.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3598,7 +3598,7 @@ AC_CHECK_FUNCS(bcmp fchdir fchown fsync getcwd getpseudotty \
35983598
getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \
35993599
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
36003600
setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
3601-
sigvec strcasecmp strerror strftime stricmp strncasecmp \
3601+
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
36023602
strnicmp strpbrk strtol tgetent towlower towupper iswupper \
36033603
usleep utime utimes)
36043604
AC_FUNC_FSEEKO

src/os_unix.c

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,15 @@ static RETSIGTYPE deathtrap SIGPROTOARG;
211211
static void catch_int_signal(void);
212212
static void set_signals(void);
213213
static void catch_signals(RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)());
214+
#ifdef HAVE_SIGPROCMASK
215+
# define SIGSET_DECL(set) sigset_t set;
216+
# define BLOCK_SIGNALS(set) block_signals(set)
217+
# define UNBLOCK_SIGNALS(set) unblock_signals(set)
218+
#else
219+
# define SIGSET_DECL(set)
220+
# define BLOCK_SIGNALS(set) do { /**/ } while (0)
221+
# define UNBLOCK_SIGNALS(set) do { /**/ } while (0)
222+
#endif
214223
static int have_wildcard(int, char_u **);
215224
static int have_dollars(int, char_u **);
216225

@@ -1468,6 +1477,33 @@ catch_signals(
14681477
signal(signal_info[i].sig, func_other);
14691478
}
14701479

1480+
#ifdef HAVE_SIGPROCMASK
1481+
static void
1482+
block_signals(sigset_t *set)
1483+
{
1484+
sigset_t newset;
1485+
int i;
1486+
1487+
sigemptyset(&newset);
1488+
1489+
for (i = 0; signal_info[i].sig != -1; i++)
1490+
sigaddset(&newset, signal_info[i].sig);
1491+
1492+
# if defined(_REENTRANT) && defined(SIGCONT)
1493+
/* SIGCONT isn't in the list, because its default action is ignore */
1494+
sigaddset(&newset, SIGCONT);
1495+
# endif
1496+
1497+
sigprocmask(SIG_BLOCK, &newset, set);
1498+
}
1499+
1500+
static void
1501+
unblock_signals(sigset_t *set)
1502+
{
1503+
sigprocmask(SIG_SETMASK, set, NULL);
1504+
}
1505+
#endif
1506+
14711507
/*
14721508
* Handling of SIGHUP, SIGQUIT and SIGTERM:
14731509
* "when" == a signal: when busy, postpone and return FALSE, otherwise
@@ -4283,12 +4319,18 @@ mch_call_shell(
42834319

42844320
if (!pipe_error) /* pty or pipe opened or not used */
42854321
{
4322+
SIGSET_DECL(curset)
4323+
42864324
# ifdef __BEOS__
42874325
beos_cleanup_read_thread();
42884326
# endif
42894327

4290-
if ((pid = fork()) == -1) /* maybe we should use vfork() */
4328+
BLOCK_SIGNALS(&curset);
4329+
pid = fork(); /* maybe we should use vfork() */
4330+
if (pid == -1)
42914331
{
4332+
UNBLOCK_SIGNALS(&curset);
4333+
42924334
MSG_PUTS(_("\nCannot fork\n"));
42934335
if ((options & (SHELL_READ|SHELL_WRITE))
42944336
# ifdef FEAT_GUI
@@ -4315,6 +4357,7 @@ mch_call_shell(
43154357
else if (pid == 0) /* child */
43164358
{
43174359
reset_signals(); /* handle signals normally */
4360+
UNBLOCK_SIGNALS(&curset);
43184361

43194362
if (!show_shell_mess || (options & SHELL_EXPAND))
43204363
{
@@ -4458,6 +4501,7 @@ mch_call_shell(
44584501
*/
44594502
catch_signals(SIG_IGN, SIG_ERR);
44604503
catch_int_signal();
4504+
UNBLOCK_SIGNALS(&curset);
44614505

44624506
/*
44634507
* 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)
50695113
int use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE;
50705114
int use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE;
50715115
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
5116+
SIGSET_DECL(curset)
50725117

50735118
if (use_out_for_err && use_null_for_out)
50745119
use_null_for_err = TRUE;
@@ -5140,20 +5185,22 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
51405185
goto failed;
51415186
}
51425187

5188+
BLOCK_SIGNALS(&curset);
51435189
pid = fork(); /* maybe we should use vfork() */
5144-
if (pid == -1)
5190+
if (pid == -1)
51455191
{
51465192
/* failed to fork */
5193+
UNBLOCK_SIGNALS(&curset);
51475194
goto failed;
51485195
}
5149-
51505196
if (pid == 0)
51515197
{
51525198
int null_fd = -1;
51535199
int stderr_works = TRUE;
51545200

51555201
/* child */
51565202
reset_signals(); /* handle signals normally */
5203+
UNBLOCK_SIGNALS(&curset);
51575204

51585205
# ifdef HAVE_SETSID
51595206
/* 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)
52345281
}
52355282

52365283
/* parent */
5284+
UNBLOCK_SIGNALS(&curset);
5285+
52375286
job->jv_pid = pid;
52385287
job->jv_status = JOB_STARTED;
52395288
job->jv_channel = channel; /* ch_refcount was set above */
@@ -5357,7 +5406,6 @@ mch_detect_ended_job(job_T *job_list)
53575406
}
53585407
}
53595408
return NULL;
5360-
53615409
}
53625410

53635411
int

src/testdir/test_channel.vim

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,6 +1433,21 @@ func Test_job_start_invalid()
14331433
call assert_fails('call job_start("")', 'E474:')
14341434
endfunc
14351435

1436+
func Test_job_stop_immediately()
1437+
if !has('job')
1438+
return
1439+
endif
1440+
1441+
let job = job_start([s:python, '-c', 'import time;time.sleep(10)'])
1442+
try
1443+
call job_stop(job)
1444+
call WaitFor('"dead" == job_status(job)')
1445+
call assert_equal('dead', job_status(job))
1446+
finally
1447+
call job_stop(job, 'kill')
1448+
endtry
1449+
endfunc
1450+
14361451
" This was leaking memory.
14371452
func Test_partial_in_channel_cycle()
14381453
let d = {}

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,8 @@ static char *(features[]) =
764764

765765
static int included_patches[] =
766766
{ /* Add new patch number below this line */
767+
/**/
768+
45,
767769
/**/
768770
44,
769771
/**/

0 commit comments

Comments
 (0)