Mercurial > vim
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 { |