diff options
| author | Paul Eggert | 2017-05-19 00:11:48 -0700 |
|---|---|---|
| committer | Paul Eggert | 2017-05-19 00:13:27 -0700 |
| commit | 7c951fd51832badb09055a8e177f8ec358cbbdcf (patch) | |
| tree | 1b77d643aa5d2719ee7e070a82f499292d60adb3 /src/sysdep.c | |
| parent | df9bec3b39b12b33db8f5a97d86797f6636e5e7d (diff) | |
| download | emacs-7c951fd51832badb09055a8e177f8ec358cbbdcf.tar.gz emacs-7c951fd51832badb09055a8e177f8ec358cbbdcf.zip | |
Attempt to work around macOS vfork bug
Problem reported by YAMAMOTO Mitsuharu in:
http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00342.html
This is related to the fix for Bug#26397.
* src/callproc.c (call_process_cleanup, call_process) [!MSDOS]:
Report internal error if wait_for_termination fails.
* src/sysdep.c (get_child_status): Return -1 if waitpid is
buggy, instead of aborting.
(wait_for_termination): Return bool success value.
All callers changed.
Diffstat (limited to 'src/sysdep.c')
| -rw-r--r-- | src/sysdep.c | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/src/sysdep.c b/src/sysdep.c index ac6eed0e581..70f4a9dd7ea 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -368,8 +368,8 @@ init_baud_rate (int fd) | |||
| 368 | Use waitpid-style OPTIONS when waiting. | 368 | Use waitpid-style OPTIONS when waiting. |
| 369 | If INTERRUPTIBLE, this function is interruptible by a signal. | 369 | If INTERRUPTIBLE, this function is interruptible by a signal. |
| 370 | 370 | ||
| 371 | Return CHILD if successful, 0 if no status is available; | 371 | Return CHILD if successful, 0 if no status is available, and a |
| 372 | the latter is possible only when options & NOHANG. */ | 372 | negative value (setting errno) if waitpid is buggy. */ |
| 373 | static pid_t | 373 | static pid_t |
| 374 | get_child_status (pid_t child, int *status, int options, bool interruptible) | 374 | get_child_status (pid_t child, int *status, int options, bool interruptible) |
| 375 | { | 375 | { |
| @@ -392,13 +392,14 @@ get_child_status (pid_t child, int *status, int options, bool interruptible) | |||
| 392 | pid = waitpid (child, status, options); | 392 | pid = waitpid (child, status, options); |
| 393 | if (0 <= pid) | 393 | if (0 <= pid) |
| 394 | break; | 394 | break; |
| 395 | |||
| 396 | /* Check that CHILD is a child process that has not been reaped, | ||
| 397 | and that STATUS and OPTIONS are valid. Otherwise abort, | ||
| 398 | as continuing after this internal error could cause Emacs to | ||
| 399 | become confused and kill innocent-victim processes. */ | ||
| 400 | if (errno != EINTR) | 395 | if (errno != EINTR) |
| 401 | emacs_abort (); | 396 | { |
| 397 | /* Most likely, waitpid is buggy and the operating system | ||
| 398 | lost track of the child somehow. Return -1 and let the | ||
| 399 | caller try to figure things out. Possibly the bug could | ||
| 400 | cause Emacs to kill the wrong process. Oh well. */ | ||
| 401 | return pid; | ||
| 402 | } | ||
| 402 | } | 403 | } |
| 403 | 404 | ||
| 404 | /* If successful and status is requested, tell wait_reading_process_output | 405 | /* If successful and status is requested, tell wait_reading_process_output |
| @@ -413,11 +414,13 @@ get_child_status (pid_t child, int *status, int options, bool interruptible) | |||
| 413 | CHILD must be a child process that has not been reaped. | 414 | CHILD must be a child process that has not been reaped. |
| 414 | If STATUS is non-null, store the waitpid-style exit status into *STATUS | 415 | If STATUS is non-null, store the waitpid-style exit status into *STATUS |
| 415 | and tell wait_reading_process_output that it needs to look around. | 416 | and tell wait_reading_process_output that it needs to look around. |
| 416 | If INTERRUPTIBLE, this function is interruptible by a signal. */ | 417 | If INTERRUPTIBLE, this function is interruptible by a signal. |
| 417 | void | 418 | Return true if successful, false (setting errno) if CHILD cannot be |
| 419 | waited for because waitpid is buggy. */ | ||
| 420 | bool | ||
| 418 | wait_for_termination (pid_t child, int *status, bool interruptible) | 421 | wait_for_termination (pid_t child, int *status, bool interruptible) |
| 419 | { | 422 | { |
| 420 | get_child_status (child, status, 0, interruptible); | 423 | return 0 <= get_child_status (child, status, 0, interruptible); |
| 421 | } | 424 | } |
| 422 | 425 | ||
| 423 | /* Report whether the subprocess with process id CHILD has changed status. | 426 | /* Report whether the subprocess with process id CHILD has changed status. |