diff options
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 99 |
1 files changed, 66 insertions, 33 deletions
diff --git a/src/process.c b/src/process.c index 17facf567b8..2e2610ffde4 100644 --- a/src/process.c +++ b/src/process.c @@ -78,7 +78,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #endif #ifdef HAVE_RES_INIT -#include <netinet/in.h> #include <arpa/nameser.h> #include <resolv.h> #endif @@ -124,8 +123,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include TERM_HEADER #endif /* HAVE_WINDOW_SYSTEM */ -#if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS) +#ifdef HAVE_GLIB #include "xgselect.h" +#ifndef WINDOWSNT +#include <glib.h> +#endif #endif #ifdef WINDOWSNT @@ -1784,12 +1786,10 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) #ifndef WINDOWSNT int wait_child_setup[2]; #endif - sigset_t blocked; - /* Use volatile to protect variables from being clobbered by vfork. */ - volatile int forkin, forkout; - volatile bool pty_flag = 0; - volatile Lisp_Object lisp_pty_name = Qnil; - volatile Lisp_Object encoded_current_dir; + int forkin, forkout; + bool pty_flag = 0; + Lisp_Object lisp_pty_name = Qnil; + Lisp_Object encoded_current_dir; inchannel = outchannel = -1; @@ -1877,15 +1877,34 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) encoded_current_dir = ENCODE_FILE (current_dir); block_input (); - - /* Block SIGCHLD until we have a chance to store the new fork's - pid in its process structure. */ - sigemptyset (&blocked); - sigaddset (&blocked, SIGCHLD); - pthread_sigmask (SIG_BLOCK, &blocked, 0); + block_child_signal (); #ifndef WINDOWSNT - pid = vfork (); + /* vfork, and prevent local vars from being clobbered by the vfork. */ + { + Lisp_Object volatile encoded_current_dir_volatile = encoded_current_dir; + Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name; + Lisp_Object volatile process_volatile = process; + bool volatile pty_flag_volatile = pty_flag; + char **volatile new_argv_volatile = new_argv; + int volatile forkin_volatile = forkin; + int volatile forkout_volatile = forkout; + int volatile wait_child_setup_0_volatile = wait_child_setup[0]; + int volatile wait_child_setup_1_volatile = wait_child_setup[1]; + + pid = vfork (); + + encoded_current_dir = encoded_current_dir_volatile; + lisp_pty_name = lisp_pty_name_volatile; + process = process_volatile; + pty_flag = pty_flag_volatile; + new_argv = new_argv_volatile; + forkin = forkin_volatile; + forkout = forkout_volatile; + wait_child_setup[0] = wait_child_setup_0_volatile; + wait_child_setup[1] = wait_child_setup_1_volatile; + } + if (pid == 0) #endif /* not WINDOWSNT */ { @@ -1990,8 +2009,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) /* Emacs ignores SIGPIPE, but the child should not. */ signal (SIGPIPE, SIG_DFL); - /* Stop blocking signals in the child. */ - pthread_sigmask (SIG_SETMASK, &empty_mask, 0); + /* Stop blocking SIGCHLD in the child. */ + unblock_child_signal (); if (pty_flag) child_setup_tty (xforkout); @@ -2011,8 +2030,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) if (pid >= 0) XPROCESS (process)->alive = 1; - /* Stop blocking signals in the parent. */ - pthread_sigmask (SIG_SETMASK, &empty_mask, 0); + /* Stop blocking in the parent. */ + unblock_child_signal (); unblock_input (); if (pid < 0) @@ -2715,7 +2734,7 @@ usage: (make-serial-process &rest ARGS) */) struct gcpro gcpro1; Lisp_Object name, buffer; Lisp_Object tem, val; - ptrdiff_t specpdl_count = -1; + ptrdiff_t specpdl_count; if (nargs == 0) return Qnil; @@ -4569,7 +4588,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, && ! EQ (wait_proc->status, Qrun) && ! EQ (wait_proc->status, Qconnect)) { - int nread, total_nread = 0; + bool read_some_bytes = 0; clear_waiting_for_input (); XSETPROCESS (proc, wait_proc); @@ -4577,16 +4596,13 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* Read data from the process, until we exhaust it. */ while (wait_proc->infd >= 0) { - nread = read_process_output (proc, wait_proc->infd); + int nread = read_process_output (proc, wait_proc->infd); if (nread == 0) break; if (nread > 0) - { - total_nread += nread; - got_some_input = 1; - } + got_some_input = read_some_bytes = 1; else if (nread == -1 && (errno == EIO || errno == EAGAIN)) break; #ifdef EWOULDBLOCK @@ -4594,7 +4610,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, break; #endif } - if (total_nread > 0 && do_display) + if (read_some_bytes && do_display) redisplay_preserve_echo_area (10); break; @@ -6257,9 +6273,10 @@ process has been transmitted to the serial port. */) /* LIB_CHILD_HANDLER is a SIGCHLD handler that Emacs calls while doing its own SIGCHLD handling. On POSIXish systems, glib needs this to - keep track of its own children. The default handler does nothing. */ + keep track of its own children. GNUstep is similar. */ + static void dummy_handler (int sig) {} -static signal_handler_t volatile lib_child_handler = dummy_handler; +static signal_handler_t volatile lib_child_handler; /* Handle a SIGCHLD signal by looking for known child processes of Emacs whose status have changed. For each one found, record its @@ -6344,6 +6361,11 @@ handle_child_signal (int sig) } lib_child_handler (sig); +#ifdef NS_IMPL_GNUSTEP + /* NSTask in GNUStep sets its child handler each time it is called. + So we must re-set ours. */ + catch_child_signal(); +#endif } static void @@ -7189,6 +7211,11 @@ integer or floating point values. return system_process_attributes (pid); } +/* Arrange to catch SIGCHLD if this hasn't already been arranged. + Invoke this after init_process_emacs, and after glib and/or GNUstep + futz with the SIGCHLD handler, but before Emacs forks any children. + This function's caller should block SIGCHLD. */ + #ifndef NS_IMPL_GNUSTEP static #endif @@ -7197,11 +7224,16 @@ catch_child_signal (void) { struct sigaction action, old_action; emacs_sigaction_init (&action, deliver_child_signal); + block_child_signal (); sigaction (SIGCHLD, &action, &old_action); eassert (! (old_action.sa_flags & SA_SIGINFO)); - if (old_action.sa_handler != SIG_DFL && old_action.sa_handler != SIG_IGN - && old_action.sa_handler != deliver_child_signal) - lib_child_handler = old_action.sa_handler; + + if (old_action.sa_handler != deliver_child_signal) + lib_child_handler + = (old_action.sa_handler == SIG_DFL || old_action.sa_handler == SIG_IGN + ? dummy_handler + : old_action.sa_handler); + unblock_child_signal (); } @@ -7222,7 +7254,8 @@ init_process_emacs (void) #if defined HAVE_GLIB && !defined WINDOWSNT /* Tickle glib's child-handling code. Ask glib to wait for Emacs itself; this should always fail, but is enough to initialize glib's - private SIGCHLD handler. */ + private SIGCHLD handler, allowing catch_child_signal to copy + it into lib_child_handler. */ g_source_unref (g_child_watch_source_new (getpid ())); #endif catch_child_signal (); |
