aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2017-05-19 00:11:48 -0700
committerPaul Eggert2017-05-19 00:13:27 -0700
commit7c951fd51832badb09055a8e177f8ec358cbbdcf (patch)
tree1b77d643aa5d2719ee7e070a82f499292d60adb3 /src
parentdf9bec3b39b12b33db8f5a97d86797f6636e5e7d (diff)
downloademacs-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')
-rw-r--r--src/callproc.c13
-rw-r--r--src/sysdep.c25
-rw-r--r--src/syswait.h2
3 files changed, 24 insertions, 16 deletions
diff --git a/src/callproc.c b/src/callproc.c
index e967e45d03f..7c85eed835f 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -202,10 +202,11 @@ call_process_cleanup (Lisp_Object buffer)
202 message1 ("Waiting for process to die...(type C-g again to kill it instantly)"); 202 message1 ("Waiting for process to die...(type C-g again to kill it instantly)");
203 203
204 /* This will quit on C-g. */ 204 /* This will quit on C-g. */
205 wait_for_termination (synch_process_pid, 0, 1); 205 bool wait_ok = wait_for_termination (synch_process_pid, NULL, true);
206
207 synch_process_pid = 0; 206 synch_process_pid = 0;
208 message1 ("Waiting for process to die...done"); 207 message1 (wait_ok
208 ? "Waiting for process to die...done"
209 : "Waiting for process to die...internal error");
209 } 210 }
210#endif /* !MSDOS */ 211#endif /* !MSDOS */
211} 212}
@@ -866,9 +867,10 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
866 make_number (total_read)); 867 make_number (total_read));
867 } 868 }
868 869
870 bool wait_ok = true;
869#ifndef MSDOS 871#ifndef MSDOS
870 /* Wait for it to terminate, unless it already has. */ 872 /* Wait for it to terminate, unless it already has. */
871 wait_for_termination (pid, &status, fd0 < 0); 873 wait_ok = wait_for_termination (pid, &status, fd0 < 0);
872#endif 874#endif
873 875
874 /* Don't kill any children that the subprocess may have left behind 876 /* Don't kill any children that the subprocess may have left behind
@@ -878,6 +880,9 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
878 SAFE_FREE (); 880 SAFE_FREE ();
879 unbind_to (count, Qnil); 881 unbind_to (count, Qnil);
880 882
883 if (!wait_ok)
884 return build_unibyte_string ("internal error");
885
881 if (WIFSIGNALED (status)) 886 if (WIFSIGNALED (status))
882 { 887 {
883 const char *signame; 888 const char *signame;
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. */
373static pid_t 373static pid_t
374get_child_status (pid_t child, int *status, int options, bool interruptible) 374get_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.
417void 418 Return true if successful, false (setting errno) if CHILD cannot be
419 waited for because waitpid is buggy. */
420bool
418wait_for_termination (pid_t child, int *status, bool interruptible) 421wait_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.
diff --git a/src/syswait.h b/src/syswait.h
index 846a975b241..055562ae48b 100644
--- a/src/syswait.h
+++ b/src/syswait.h
@@ -56,7 +56,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
56#endif 56#endif
57 57
58/* Defined in sysdep.c. */ 58/* Defined in sysdep.c. */
59extern void wait_for_termination (pid_t, int *, bool); 59extern bool wait_for_termination (pid_t, int *, bool);
60extern pid_t child_status_changed (pid_t, int *, int); 60extern pid_t child_status_changed (pid_t, int *, int);
61 61
62#endif /* EMACS_SYSWAIT_H */ 62#endif /* EMACS_SYSWAIT_H */