comparison src/os_unix.c @ 10297:c90f4cc9c3fe v8.0.0045

commit https://github.com/vim/vim/commit/bb09ceb95477ecc271854b3fdd8d2776eca66adf Author: Bram Moolenaar <Bram@vim.org> Date: Tue Oct 18 16:27:23 2016 +0200 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 https://github.com/vim/vim/issues/1155)
author Christian Brabandt <cb@256bit.org>
date Tue, 18 Oct 2016 16:30:04 +0200
parents c5c15c818bda
children 88331ee68367
comparison
equal deleted inserted replaced
10296:5197102a03f8 10297:c90f4cc9c3fe
209 static RETSIGTYPE deathtrap SIGPROTOARG; 209 static RETSIGTYPE deathtrap SIGPROTOARG;
210 210
211 static void catch_int_signal(void); 211 static void catch_int_signal(void);
212 static void set_signals(void); 212 static void set_signals(void);
213 static void catch_signals(RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()); 213 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
214 static int have_wildcard(int, char_u **); 223 static int have_wildcard(int, char_u **);
215 static int have_dollars(int, char_u **); 224 static int have_dollars(int, char_u **);
216 225
217 static int save_patterns(int num_pat, char_u **pat, int *num_file, char_u ***file); 226 static int save_patterns(int num_pat, char_u **pat, int *num_file, char_u ***file);
218 227
1465 #endif 1474 #endif
1466 } 1475 }
1467 else if (func_other != SIG_ERR) 1476 else if (func_other != SIG_ERR)
1468 signal(signal_info[i].sig, func_other); 1477 signal(signal_info[i].sig, func_other);
1469 } 1478 }
1479
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
1470 1506
1471 /* 1507 /*
1472 * Handling of SIGHUP, SIGQUIT and SIGTERM: 1508 * Handling of SIGHUP, SIGQUIT and SIGTERM:
1473 * "when" == a signal: when busy, postpone and return FALSE, otherwise 1509 * "when" == a signal: when busy, postpone and return FALSE, otherwise
1474 * return TRUE 1510 * return TRUE
4281 } 4317 }
4282 } 4318 }
4283 4319
4284 if (!pipe_error) /* pty or pipe opened or not used */ 4320 if (!pipe_error) /* pty or pipe opened or not used */
4285 { 4321 {
4322 SIGSET_DECL(curset)
4323
4286 # ifdef __BEOS__ 4324 # ifdef __BEOS__
4287 beos_cleanup_read_thread(); 4325 beos_cleanup_read_thread();
4288 # endif 4326 # endif
4289 4327
4290 if ((pid = fork()) == -1) /* maybe we should use vfork() */ 4328 BLOCK_SIGNALS(&curset);
4291 { 4329 pid = fork(); /* maybe we should use vfork() */
4330 if (pid == -1)
4331 {
4332 UNBLOCK_SIGNALS(&curset);
4333
4292 MSG_PUTS(_("\nCannot fork\n")); 4334 MSG_PUTS(_("\nCannot fork\n"));
4293 if ((options & (SHELL_READ|SHELL_WRITE)) 4335 if ((options & (SHELL_READ|SHELL_WRITE))
4294 # ifdef FEAT_GUI 4336 # ifdef FEAT_GUI
4295 || (gui.in_use && show_shell_mess) 4337 || (gui.in_use && show_shell_mess)
4296 # endif 4338 # endif
4313 } 4355 }
4314 } 4356 }
4315 else if (pid == 0) /* child */ 4357 else if (pid == 0) /* child */
4316 { 4358 {
4317 reset_signals(); /* handle signals normally */ 4359 reset_signals(); /* handle signals normally */
4360 UNBLOCK_SIGNALS(&curset);
4318 4361
4319 if (!show_shell_mess || (options & SHELL_EXPAND)) 4362 if (!show_shell_mess || (options & SHELL_EXPAND))
4320 { 4363 {
4321 int fd; 4364 int fd;
4322 4365
4456 * While child is running, ignore terminating signals. 4499 * While child is running, ignore terminating signals.
4457 * Do catch CTRL-C, so that "got_int" is set. 4500 * Do catch CTRL-C, so that "got_int" is set.
4458 */ 4501 */
4459 catch_signals(SIG_IGN, SIG_ERR); 4502 catch_signals(SIG_IGN, SIG_ERR);
4460 catch_int_signal(); 4503 catch_int_signal();
4504 UNBLOCK_SIGNALS(&curset);
4461 4505
4462 /* 4506 /*
4463 * For the GUI we redirect stdin, stdout and stderr to our window. 4507 * For the GUI we redirect stdin, stdout and stderr to our window.
4464 * This is also used to pipe stdin/stdout to/from the external 4508 * This is also used to pipe stdin/stdout to/from the external
4465 * command. 4509 * command.
5067 int use_null_for_err = options->jo_io[PART_ERR] == JIO_NULL; 5111 int use_null_for_err = options->jo_io[PART_ERR] == JIO_NULL;
5068 int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE; 5112 int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
5069 int use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE; 5113 int use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE;
5070 int use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE; 5114 int use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE;
5071 int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT; 5115 int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
5116 SIGSET_DECL(curset)
5072 5117
5073 if (use_out_for_err && use_null_for_out) 5118 if (use_out_for_err && use_null_for_out)
5074 use_null_for_err = TRUE; 5119 use_null_for_err = TRUE;
5075 5120
5076 /* default is to fail */ 5121 /* default is to fail */
5138 channel = add_channel(); 5183 channel = add_channel();
5139 if (channel == NULL) 5184 if (channel == NULL)
5140 goto failed; 5185 goto failed;
5141 } 5186 }
5142 5187
5188 BLOCK_SIGNALS(&curset);
5143 pid = fork(); /* maybe we should use vfork() */ 5189 pid = fork(); /* maybe we should use vfork() */
5144 if (pid == -1) 5190 if (pid == -1)
5145 { 5191 {
5146 /* failed to fork */ 5192 /* failed to fork */
5193 UNBLOCK_SIGNALS(&curset);
5147 goto failed; 5194 goto failed;
5148 } 5195 }
5149
5150 if (pid == 0) 5196 if (pid == 0)
5151 { 5197 {
5152 int null_fd = -1; 5198 int null_fd = -1;
5153 int stderr_works = TRUE; 5199 int stderr_works = TRUE;
5154 5200
5155 /* child */ 5201 /* child */
5156 reset_signals(); /* handle signals normally */ 5202 reset_signals(); /* handle signals normally */
5203 UNBLOCK_SIGNALS(&curset);
5157 5204
5158 # ifdef HAVE_SETSID 5205 # ifdef HAVE_SETSID
5159 /* Create our own process group, so that the child and all its 5206 /* Create our own process group, so that the child and all its
5160 * children can be kill()ed. Don't do this when using pipes, 5207 * children can be kill()ed. Don't do this when using pipes,
5161 * because stdin is not a tty, we would lose /dev/tty. */ 5208 * because stdin is not a tty, we would lose /dev/tty. */
5232 #endif 5279 #endif
5233 _exit(EXEC_FAILED); /* exec failed, return failure code */ 5280 _exit(EXEC_FAILED); /* exec failed, return failure code */
5234 } 5281 }
5235 5282
5236 /* parent */ 5283 /* parent */
5284 UNBLOCK_SIGNALS(&curset);
5285
5237 job->jv_pid = pid; 5286 job->jv_pid = pid;
5238 job->jv_status = JOB_STARTED; 5287 job->jv_status = JOB_STARTED;
5239 job->jv_channel = channel; /* ch_refcount was set above */ 5288 job->jv_channel = channel; /* ch_refcount was set above */
5240 5289
5241 /* child stdin, stdout and stderr */ 5290 /* child stdin, stdout and stderr */
5355 } 5404 }
5356 return job; 5405 return job;
5357 } 5406 }
5358 } 5407 }
5359 return NULL; 5408 return NULL;
5360
5361 } 5409 }
5362 5410
5363 int 5411 int
5364 mch_stop_job(job_T *job, char_u *how) 5412 mch_stop_job(job_T *job, char_u *how)
5365 { 5413 {