]> code.delx.au - gnu-emacs/blobdiff - src/process.c
* buffer.c (Fset_buffer_major_mode): Doc fix.
[gnu-emacs] / src / process.c
index 0ae68567d6bab3b46d190cefb43614f698d33d11..77e99ead01f1d7361c1f7693a0f407bae1075a2f 100644 (file)
@@ -25,12 +25,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <stdio.h>
 #include <errno.h>
-#include <setjmp.h>
 #include <sys/types.h>         /* Some typedefs are used in sys/file.h.  */
 #include <sys/file.h>
 #include <sys/stat.h>
-#include <setjmp.h>
-
 #include <unistd.h>
 #include <fcntl.h>
 
@@ -75,6 +72,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <bsdtty.h>
 #endif
 
+#ifdef USG5_4
+# include <sys/stream.h>
+# include <sys/stropts.h>
+#endif
+
 #ifdef HAVE_RES_INIT
 #include <netinet/in.h>
 #include <arpa/nameser.h>
@@ -123,6 +125,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "xgselect.h"
 #endif
 
+#ifdef WINDOWSNT
+extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
+                      EMACS_TIME *, void *);
+#endif
+
 #ifndef WNOHANG
 # undef waitpid
 # define waitpid(pid, status, options) wait (status)
@@ -212,17 +219,13 @@ static EMACS_INT update_tick;
    "non-destructive" select.  So we require either native select,
    or emulation of select using FIONREAD.  */
 
-#ifdef BROKEN_DATAGRAM_SOCKETS
-#undef DATAGRAM_SOCKETS
-#else
-#ifndef DATAGRAM_SOCKETS
-#if defined (HAVE_SELECT) || defined (FIONREAD)
-#if defined (HAVE_SENDTO) && defined (HAVE_RECVFROM) && defined (EMSGSIZE)
-#define DATAGRAM_SOCKETS
-#endif /* HAVE_SENDTO && HAVE_RECVFROM && EMSGSIZE */
-#endif /* HAVE_SELECT || FIONREAD */
-#endif /* DATAGRAM_SOCKETS */
-#endif /* BROKEN_DATAGRAM_SOCKETS */
+#ifndef BROKEN_DATAGRAM_SOCKETS
+# if defined HAVE_SELECT || defined USABLE_FIONREAD
+#  if defined HAVE_SENDTO && defined HAVE_RECVFROM && defined EMSGSIZE
+#   define DATAGRAM_SOCKETS
+#  endif
+# endif
+#endif
 
 #if defined HAVE_LOCAL_SOCKETS && defined DATAGRAM_SOCKETS
 # define HAVE_SEQPACKET
@@ -251,17 +254,18 @@ static int process_output_skip;
 #endif
 
 static void create_process (Lisp_Object, char **, Lisp_Object);
-#ifdef SIGIO
+#ifdef USABLE_SIGIO
 static int keyboard_bit_set (SELECT_TYPE *);
 #endif
 static void deactivate_process (Lisp_Object);
 static void status_notify (struct Lisp_Process *);
 static int read_process_output (Lisp_Object, int);
+static void handle_child_signal (int);
 static void create_pty (Lisp_Object);
 
 /* If we support a window system, turn on the code to poll periodically
    to detect C-g.  It isn't actually used when doing interrupt input.  */
-#if defined (HAVE_WINDOW_SYSTEM) && !defined (USE_ASYNC_EVENTS)
+#ifdef HAVE_WINDOW_SYSTEM
 #define POLL_FOR_INPUT
 #endif
 
@@ -336,82 +340,82 @@ static struct sockaddr_and_len {
 static int pty_max_bytes;
 
 /* These setters are used only in this file, so they can be private.  */
-static inline void
+static void
 pset_buffer (struct Lisp_Process *p, Lisp_Object val)
 {
   p->buffer = val;
 }
-static inline void
+static void
 pset_command (struct Lisp_Process *p, Lisp_Object val)
 {
   p->command = val;
 }
-static inline void
+static void
 pset_decode_coding_system (struct Lisp_Process *p, Lisp_Object val)
 {
   p->decode_coding_system = val;
 }
-static inline void
+static void
 pset_decoding_buf (struct Lisp_Process *p, Lisp_Object val)
 {
   p->decoding_buf = val;
 }
-static inline void
+static void
 pset_encode_coding_system (struct Lisp_Process *p, Lisp_Object val)
 {
   p->encode_coding_system = val;
 }
-static inline void
+static void
 pset_encoding_buf (struct Lisp_Process *p, Lisp_Object val)
 {
   p->encoding_buf = val;
 }
-static inline void
+static void
 pset_filter (struct Lisp_Process *p, Lisp_Object val)
 {
   p->filter = val;
 }
-static inline void
+static void
 pset_log (struct Lisp_Process *p, Lisp_Object val)
 {
   p->log = val;
 }
-static inline void
+static void
 pset_mark (struct Lisp_Process *p, Lisp_Object val)
 {
   p->mark = val;
 }
-static inline void
+static void
 pset_name (struct Lisp_Process *p, Lisp_Object val)
 {
   p->name = val;
 }
-static inline void
+static void
 pset_plist (struct Lisp_Process *p, Lisp_Object val)
 {
   p->plist = val;
 }
-static inline void
+static void
 pset_sentinel (struct Lisp_Process *p, Lisp_Object val)
 {
   p->sentinel = val;
 }
-static inline void
+static void
 pset_status (struct Lisp_Process *p, Lisp_Object val)
 {
   p->status = val;
 }
-static inline void
+static void
 pset_tty_name (struct Lisp_Process *p, Lisp_Object val)
 {
   p->tty_name = val;
 }
-static inline void
+static void
 pset_type (struct Lisp_Process *p, Lisp_Object val)
 {
   p->type = val;
 }
-static inline void
+static void
 pset_write_queue (struct Lisp_Process *p, Lisp_Object val)
 {
   p->write_queue = val;
@@ -571,7 +575,7 @@ status_message (struct Lisp_Process *p)
 
   if (EQ (symbol, Qsignal) || EQ (symbol, Qstop))
     {
-      char *signame;
+      char const *signame;
       synchronize_system_messages_locale ();
       signame = strsignal (code);
       if (signame == 0)
@@ -647,23 +651,6 @@ allocate_pty (void)
        PTY_OPEN;
 #else /* no PTY_OPEN */
        {
-         { /* Some systems name their pseudoterminals so that there are gaps in
-              the usual sequence - for example, on HP9000/S700 systems, there
-              are no pseudoterminals with names ending in 'f'.  So we wait for
-              three failures in a row before deciding that we've reached the
-              end of the ptys.  */
-           int failed_count = 0;
-           struct stat stb;
-
-           if (stat (pty_name, &stb) < 0)
-             {
-               failed_count++;
-               if (failed_count >= 3)
-                 return -1;
-             }
-           else
-             failed_count = 0;
-         }
 #  ifdef O_NONBLOCK
          fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0);
 #  else
@@ -1611,16 +1598,17 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 #if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
   int wait_child_setup[2];
 #endif
-  sigset_t blocked, procmask;
-  struct sigaction sigint_action;
-  struct sigaction sigquit_action;
-  struct sigaction sigpipe_action;
-#ifdef AIX
-  struct sigaction sighup_action;
+#ifdef SIGCHLD
+  sigset_t blocked;
 #endif
-  /* Use volatile to protect variables from being clobbered by longjmp.  */
+  /* Use volatile to protect variables from being clobbered by vfork.  */
   volatile int forkin, forkout;
   volatile int pty_flag = 0;
+  volatile Lisp_Object lisp_pty_name = Qnil;
+  volatile Lisp_Object encoded_current_dir;
+#if HAVE_WORKING_VFORK
+  char **volatile save_environ;
+#endif
 
   inchannel = outchannel = -1;
 
@@ -1646,6 +1634,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
       forkin = forkout = -1;
 #endif /* not USG, or USG_SUBTTY_WORKS */
       pty_flag = 1;
+      lisp_pty_name = build_string (pty_name);
     }
   else
 #endif /* HAVE_PTYS */
@@ -1710,26 +1699,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
   XPROCESS (process)->pty_flag = pty_flag;
   pset_status (XPROCESS (process), Qrun);
 
-  /* Delay interrupts until we have a chance to store
-     the new fork's pid in its process structure */
-  sigemptyset (&blocked);
-#ifdef SIGCHLD
-  sigaddset (&blocked, SIGCHLD);
-#endif
-#ifdef HAVE_WORKING_VFORK
-  /* On many hosts (e.g. Solaris 2.4), if a vforked child calls `signal',
-     this sets the parent's signal handlers as well as the child's.
-     So delay all interrupts whose handlers the child might munge,
-     and record the current handlers so they can be restored later.  */
-  sigaddset (&blocked, SIGINT );  sigaction (SIGINT , 0, &sigint_action );
-  sigaddset (&blocked, SIGQUIT);  sigaction (SIGQUIT, 0, &sigquit_action);
-  sigaddset (&blocked, SIGPIPE);  sigaction (SIGPIPE, 0, &sigpipe_action);
-#ifdef AIX
-  sigaddset (&blocked, SIGHUP );  sigaction (SIGHUP , 0, &sighup_action );
-#endif
-#endif /* HAVE_WORKING_VFORK */
-  pthread_sigmask (SIG_BLOCK, &blocked, &procmask);
-
   FD_SET (inchannel, &input_wait_mask);
   FD_SET (inchannel, &non_keyboard_wait_mask);
   if (inchannel > max_process_desc)
@@ -1747,89 +1716,93 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
      error. */
   setup_process_coding_systems (process);
 
-  BLOCK_INPUT;
+  encoded_current_dir = ENCODE_FILE (current_dir);
 
-  {
-    /* child_setup must clobber environ on systems with true vfork.
-       Protect it from permanent change.  */
-    char **save_environ = environ;
-    volatile Lisp_Object encoded_current_dir = ENCODE_FILE (current_dir);
+  block_input ();
+
+#ifdef SIGCHLD
+  /* 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);
+#endif
+
+#if HAVE_WORKING_VFORK
+  /* child_setup must clobber environ on systems with true vfork.
+     Protect it from permanent change.  */
+  save_environ = environ;
+#endif
 
 #ifndef WINDOWSNT
-    pid = vfork ();
-    if (pid == 0)
+  pid = vfork ();
+  if (pid == 0)
 #endif /* not WINDOWSNT */
-      {
-       int xforkin = forkin;
-       int xforkout = forkout;
+    {
+      int xforkin = forkin;
+      int xforkout = forkout;
 
-       /* Make the pty be the controlling terminal of the process.  */
+      /* Make the pty be the controlling terminal of the process.  */
 #ifdef HAVE_PTYS
-       /* First, disconnect its current controlling terminal.  */
+      /* First, disconnect its current controlling terminal.  */
 #ifdef HAVE_SETSID
-       /* We tried doing setsid only if pty_flag, but it caused
-          process_set_signal to fail on SGI when using a pipe.  */
-       setsid ();
-       /* Make the pty's terminal the controlling terminal.  */
-       if (pty_flag && xforkin >= 0)
-         {
+      /* We tried doing setsid only if pty_flag, but it caused
+        process_set_signal to fail on SGI when using a pipe.  */
+      setsid ();
+      /* Make the pty's terminal the controlling terminal.  */
+      if (pty_flag && xforkin >= 0)
+       {
 #ifdef TIOCSCTTY
-           /* We ignore the return value
-              because faith@cs.unc.edu says that is necessary on Linux.  */
-           ioctl (xforkin, TIOCSCTTY, 0);
+         /* We ignore the return value
+            because faith@cs.unc.edu says that is necessary on Linux.  */
+         ioctl (xforkin, TIOCSCTTY, 0);
 #endif
-         }
+       }
 #else /* not HAVE_SETSID */
-#ifdef USG
-       /* It's very important to call setpgrp here and no time
-          afterwards.  Otherwise, we lose our controlling tty which
-          is set when we open the pty. */
-       setpgrp ();
-#endif /* USG */
+      /* It's very important to call setpgid here and no time
+        afterwards.  Otherwise, we lose our controlling tty which
+        is set when we open the pty. */
+      setpgid (0, 0);
 #endif /* not HAVE_SETSID */
 #if defined (LDISC1)
-       if (pty_flag && xforkin >= 0)
-         {
-           struct termios t;
-           tcgetattr (xforkin, &t);
-           t.c_lflag = LDISC1;
-           if (tcsetattr (xforkin, TCSANOW, &t) < 0)
-             emacs_write (1, "create_process/tcsetattr LDISC1 failed\n", 39);
-         }
+      if (pty_flag && xforkin >= 0)
+       {
+         struct termios t;
+         tcgetattr (xforkin, &t);
+         t.c_lflag = LDISC1;
+         if (tcsetattr (xforkin, TCSANOW, &t) < 0)
+           emacs_write (1, "create_process/tcsetattr LDISC1 failed\n", 39);
+       }
 #else
 #if defined (NTTYDISC) && defined (TIOCSETD)
-       if (pty_flag && xforkin >= 0)
-         {
-           /* Use new line discipline.  */
-           int ldisc = NTTYDISC;
-           ioctl (xforkin, TIOCSETD, &ldisc);
-         }
+      if (pty_flag && xforkin >= 0)
+       {
+         /* Use new line discipline.  */
+         int ldisc = NTTYDISC;
+         ioctl (xforkin, TIOCSETD, &ldisc);
+       }
 #endif
 #endif
 #ifdef TIOCNOTTY
-       /* In 4.3BSD, the TIOCSPGRP bug has been fixed, and now you
-          can do TIOCSPGRP only to the process's controlling tty.  */
-       if (pty_flag)
-         {
-           /* I wonder: would just ioctl (0, TIOCNOTTY, 0) work here?
-              I can't test it since I don't have 4.3.  */
-           int j = emacs_open ("/dev/tty", O_RDWR, 0);
-           if (j >= 0)
-             {
-               ioctl (j, TIOCNOTTY, 0);
-               emacs_close (j);
-             }
+      /* In 4.3BSD, the TIOCSPGRP bug has been fixed, and now you
+        can do TIOCSPGRP only to the process's controlling tty.  */
+      if (pty_flag)
+       {
+         /* I wonder: would just ioctl (0, TIOCNOTTY, 0) work here?
+            I can't test it since I don't have 4.3.  */
+         int j = emacs_open ("/dev/tty", O_RDWR, 0);
+         if (j >= 0)
+           {
+             ioctl (j, TIOCNOTTY, 0);
+             emacs_close (j);
+           }
 #ifndef USG
-           /* In order to get a controlling terminal on some versions
-              of BSD, it is necessary to put the process in pgrp 0
-              before it opens the terminal.  */
-#ifdef HAVE_SETPGID
-           setpgid (0, 0);
-#else
-           setpgrp (0, 0);
+         /* In order to get a controlling terminal on some versions
+            of BSD, it is necessary to put the process in pgrp 0
+            before it opens the terminal.  */
+         setpgid (0, 0);
 #endif
-#endif
-         }
+       }
 #endif /* TIOCNOTTY */
 
 #if !defined (DONT_REOPEN_PTY)
@@ -1841,68 +1814,79 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
      both HAVE_SETSID and TIOCSCTTY are defined.  */
        /* Now close the pty (if we had it open) and reopen it.
           This makes the pty the controlling terminal of the subprocess.  */
-       if (pty_flag)
-         {
+      if (pty_flag)
+       {
 
-           /* I wonder if emacs_close (emacs_open (pty_name, ...))
-              would work?  */
-           if (xforkin >= 0)
-             emacs_close (xforkin);
-           xforkout = xforkin = emacs_open (pty_name, O_RDWR, 0);
+         /* I wonder if emacs_close (emacs_open (pty_name, ...))
+            would work?  */
+         if (xforkin >= 0)
+           emacs_close (xforkin);
+         xforkout = xforkin = emacs_open (pty_name, O_RDWR, 0);
 
-           if (xforkin < 0)
-             {
-               emacs_write (1, "Couldn't open the pty terminal ", 31);
-               emacs_write (1, pty_name, strlen (pty_name));
-               emacs_write (1, "\n", 1);
-               _exit (1);
-             }
+         if (xforkin < 0)
+           {
+             emacs_write (1, "Couldn't open the pty terminal ", 31);
+             emacs_write (1, pty_name, strlen (pty_name));
+             emacs_write (1, "\n", 1);
+             _exit (1);
+           }
 
-         }
+       }
 #endif /* not DONT_REOPEN_PTY */
 
 #ifdef SETUP_SLAVE_PTY
-       if (pty_flag)
-         {
-           SETUP_SLAVE_PTY;
-         }
+      if (pty_flag)
+       {
+         SETUP_SLAVE_PTY;
+       }
 #endif /* SETUP_SLAVE_PTY */
 #ifdef AIX
-       /* On AIX, we've disabled SIGHUP above once we start a child on a pty.
-          Now reenable it in the child, so it will die when we want it to.  */
-       if (pty_flag)
-         signal (SIGHUP, SIG_DFL);
+      /* On AIX, we've disabled SIGHUP above once we start a child on a pty.
+        Now reenable it in the child, so it will die when we want it to.  */
+      if (pty_flag)
+       signal (SIGHUP, SIG_DFL);
 #endif
 #endif /* HAVE_PTYS */
 
-       signal (SIGINT, SIG_DFL);
-       signal (SIGQUIT, SIG_DFL);
-       /* GConf causes us to ignore SIGPIPE, make sure it is restored
-          in the child.  */
-       signal (SIGPIPE, SIG_DFL);
+      signal (SIGINT, SIG_DFL);
+      signal (SIGQUIT, SIG_DFL);
+
+      /* Emacs ignores SIGPIPE, but the child should not.  */
+      signal (SIGPIPE, SIG_DFL);
 
+#ifdef SIGCHLD
        /* Stop blocking signals in the child.  */
-       pthread_sigmask (SIG_SETMASK, &procmask, 0);
+      pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+#endif
 
-       if (pty_flag)
-         child_setup_tty (xforkout);
+      if (pty_flag)
+       child_setup_tty (xforkout);
 #ifdef WINDOWSNT
-       pid = child_setup (xforkin, xforkout, xforkout,
-                          new_argv, 1, encoded_current_dir);
+      pid = child_setup (xforkin, xforkout, xforkout,
+                        new_argv, 1, encoded_current_dir);
 #else  /* not WINDOWSNT */
 #ifdef FD_CLOEXEC
-       emacs_close (wait_child_setup[0]);
+      emacs_close (wait_child_setup[0]);
 #endif
-       child_setup (xforkin, xforkout, xforkout,
-                    new_argv, 1, encoded_current_dir);
+      child_setup (xforkin, xforkout, xforkout,
+                  new_argv, 1, encoded_current_dir);
 #endif /* not WINDOWSNT */
-      }
-    environ = save_environ;
-  }
+    }
+
+  /* Back in the parent process.  */
+
+#if HAVE_WORKING_VFORK
+  environ = save_environ;
+#endif
 
-  UNBLOCK_INPUT;
+  XPROCESS (process)->pid = pid;
+
+  /* Stop blocking signals in the parent.  */
+#ifdef SIGCHLD
+  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+#endif
+  unblock_input ();
 
-  /* This runs in the Emacs process.  */
   if (pid < 0)
     {
       if (forkin >= 0)
@@ -1913,7 +1897,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
   else
     {
       /* vfork succeeded.  */
-      XPROCESS (process)->pid = pid;
 
 #ifdef WINDOWSNT
       register_child (pid, inchannel);
@@ -1939,12 +1922,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
       if (forkin != forkout && forkout >= 0)
        emacs_close (forkout);
 
-#ifdef HAVE_PTYS
-      if (pty_flag)
-       pset_tty_name (XPROCESS (process), build_string (pty_name));
-      else
-#endif
-       pset_tty_name (XPROCESS (process), Qnil);
+      pset_tty_name (XPROCESS (process), lisp_pty_name);
 
 #if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
       /* Wait for child_setup to complete in case that vfork is
@@ -1961,20 +1939,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 #endif
     }
 
-  /* Restore the signal state whether vfork succeeded or not.
-     (We will signal an error, below, if it failed.)  */
-#ifdef HAVE_WORKING_VFORK
-  /* Restore the parent's signal handlers.  */
-  sigaction (SIGINT, &sigint_action, 0);
-  sigaction (SIGQUIT, &sigquit_action, 0);
-  sigaction (SIGPIPE, &sigpipe_action, 0);
-#ifdef AIX
-  sigaction (SIGHUP, &sighup_action, 0);
-#endif
-#endif /* HAVE_WORKING_VFORK */
-  /* Stop blocking signals in the parent.  */
-  pthread_sigmask (SIG_SETMASK, &procmask, 0);
-
   /* Now generate the error if vfork failed.  */
   if (pid < 0)
     report_file_error ("Doing vfork", Qnil);
@@ -3427,9 +3391,9 @@ usage: (make-network-process &rest ARGS)  */)
 #ifdef HAVE_GETADDRINFO
   if (res != &ai)
     {
-      BLOCK_INPUT;
+      block_input ();
       freeaddrinfo (res);
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 #endif
 
@@ -4320,7 +4284,7 @@ wait_reading_process_output_1 (void)
      -1 meaning caller will actually read the input, so don't throw to
        the quit handler, or
 
-   DO_DISPLAY != 0 means redisplay should be done to show subprocess
+   DO_DISPLAY means redisplay should be done to show subprocess
      output that arrives.
 
    If WAIT_FOR_CELL is a cons cell, wait until its car is non-nil
@@ -4340,7 +4304,7 @@ wait_reading_process_output_1 (void)
 
 int
 wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
-                            int do_display,
+                            bool do_display,
                             Lisp_Object wait_for_cell,
                             struct Lisp_Process *wait_proc, int just_wait_proc)
 {
@@ -4397,10 +4361,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
         Otherwise, do pending quit if requested.  */
       if (read_kbd >= 0)
        QUIT;
-#ifdef SYNC_INPUT
-      else
+      else if (pending_signals)
        process_pending_signals ();
-#endif
 
       /* Exit now if the cell we're waiting for became non-nil.  */
       if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell)))
@@ -4439,7 +4401,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
          do
            {
-             int old_timers_run = timers_run;
+             unsigned old_timers_run = timers_run;
              struct buffer *old_buffer = current_buffer;
              Lisp_Object old_window = selected_window;
 
@@ -4666,6 +4628,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
              process_output_skip = 0;
            }
 #endif
+
 #if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS)
           nfds = xg_select
 #elif defined (HAVE_NS)
@@ -4766,28 +4729,13 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
          check_write = 0;
        }
 
-#if 0 /* When polling is used, interrupt_input is 0,
-        so get_input_pending should read the input.
-        So this should not be needed.  */
-      /* If we are using polling for input,
-        and we see input available, make it get read now.
-        Otherwise it might not actually get read for a second.
-        And on hpux, since we turn off polling in wait_reading_process_output,
-        it might never get read at all if we don't spend much time
-        outside of wait_reading_process_output.  */
-      if (read_kbd && interrupt_input
-         && keyboard_bit_set (&Available)
-         && input_polling_used ())
-       kill (getpid (), SIGALRM);
-#endif
-
       /* Check for keyboard input */
       /* If there is any, return immediately
         to give it higher priority than subprocesses */
 
       if (read_kbd != 0)
        {
-         int old_timers_run = timers_run;
+         unsigned old_timers_run = timers_run;
          struct buffer *old_buffer = current_buffer;
          Lisp_Object old_window = selected_window;
          int leave = 0;
@@ -4836,7 +4784,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
       if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell)))
        break;
 
-#ifdef SIGIO
+#ifdef USABLE_SIGIO
       /* If we think we have keyboard input waiting, but didn't get SIGIO,
         go read it.  This can happen with X on BSD after logging out.
         In that case, there really is no input and no SIGIO,
@@ -4844,7 +4792,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
       if (read_kbd && interrupt_input
          && keyboard_bit_set (&Available) && ! noninteractive)
-       kill (getpid (), SIGIO);
+       handle_input_available_signal (SIGIO);
 #endif
 
       if (! wait_proc)
@@ -4964,7 +4912,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                      pset_status (p, Qfailed);
                    }
                   else
-                   kill (getpid (), SIGCHLD);
+                   handle_child_signal (SIGCHLD);
                }
 #endif /* HAVE_PTYS */
              /* If we can detect process termination, don't consider the
@@ -5420,25 +5368,6 @@ read_process_output (Lisp_Object proc, register int channel)
 \f
 /* Sending data to subprocess */
 
-static jmp_buf send_process_frame;
-static Lisp_Object process_sent_to;
-
-static _Noreturn void
-handle_pipe_signal (int sig)
-{
-  sigset_t unblocked;
-  sigemptyset (&unblocked);
-  sigaddset (&unblocked, SIGPIPE);
-  pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
-  _longjmp (send_process_frame, 1);
-}
-
-static void
-deliver_pipe_signal (int sig)
-{
-  handle_on_main_thread (sig, handle_pipe_signal);
-}
-
 /* In send_process, when a write fails temporarily,
    wait_reading_process_output is called.  It may execute user code,
    e.g. timers, that attempts to write new data to the same process.
@@ -5522,14 +5451,12 @@ write_queue_pop (struct Lisp_Process *p, Lisp_Object *obj,
    This function can evaluate Lisp code and can garbage collect.  */
 
 static void
-send_process (volatile Lisp_Object proc, const char *volatile buf,
-             volatile ptrdiff_t len, volatile Lisp_Object object)
+send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
+             Lisp_Object object)
 {
-  /* Use volatile to protect variables from being clobbered by longjmp.  */
   struct Lisp_Process *p = XPROCESS (proc);
   ssize_t rv;
   struct coding_system *coding;
-  struct sigaction old_sigpipe_action;
 
   if (p->raw_status_new)
     update_status (p);
@@ -5636,145 +5563,126 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
       pty_max_bytes--;
     }
 
-  /* 2000-09-21: Emacs 20.7, sparc-sun-solaris-2.6, GCC 2.95.2,
-     CFLAGS="-g -O": The value of the parameter `proc' is clobbered
-     when returning with longjmp despite being declared volatile.  */
-  if (!_setjmp (send_process_frame))
-    {
-      p = XPROCESS (proc);  /* Repair any setjmp clobbering.  */
-      process_sent_to = proc;
+  /* If there is already data in the write_queue, put the new data
+     in the back of queue.  Otherwise, ignore it.  */
+  if (!NILP (p->write_queue))
+    write_queue_push (p, object, buf, len, 0);
 
-      /* If there is already data in the write_queue, put the new data
-         in the back of queue.  Otherwise, ignore it.  */
-      if (!NILP (p->write_queue))
-        write_queue_push (p, object, buf, len, 0);
+  do   /* while !NILP (p->write_queue) */
+    {
+      ptrdiff_t cur_len = -1;
+      const char *cur_buf;
+      Lisp_Object cur_object;
 
-      do   /* while !NILP (p->write_queue) */
+      /* If write_queue is empty, ignore it.  */
+      if (!write_queue_pop (p, &cur_object, &cur_buf, &cur_len))
        {
-         ptrdiff_t cur_len = -1;
-         const char *cur_buf;
-         Lisp_Object cur_object;
+         cur_len = len;
+         cur_buf = buf;
+         cur_object = object;
+       }
 
-         /* If write_queue is empty, ignore it.  */
-         if (!write_queue_pop (p, &cur_object, &cur_buf, &cur_len))
+      while (cur_len > 0)
+       {
+         /* Send this batch, using one or more write calls.  */
+         ptrdiff_t written = 0;
+         int outfd = p->outfd;
+#ifdef DATAGRAM_SOCKETS
+         if (DATAGRAM_CHAN_P (outfd))
            {
-             cur_len = len;
-             cur_buf = buf;
-             cur_object = object;
+             rv = sendto (outfd, cur_buf, cur_len,
+                          0, datagram_address[outfd].sa,
+                          datagram_address[outfd].len);
+             if (0 <= rv)
+               written = rv;
+             else if (errno == EMSGSIZE)
+               report_file_error ("sending datagram", Fcons (proc, Qnil));
            }
-
-         while (cur_len > 0)
-           {
-             /* Send this batch, using one or more write calls.  */
-             ptrdiff_t written = 0;
-             int outfd = p->outfd;
-             struct sigaction action;
-             emacs_sigaction_init (&action, deliver_pipe_signal);
-             sigaction (SIGPIPE, &action, &old_sigpipe_action);
-#ifdef DATAGRAM_SOCKETS
-             if (DATAGRAM_CHAN_P (outfd))
-               {
-                 rv = sendto (outfd, cur_buf, cur_len,
-                              0, datagram_address[outfd].sa,
-                              datagram_address[outfd].len);
-                 if (0 <= rv)
-                   written = rv;
-                 else if (errno == EMSGSIZE)
-                   {
-                     sigaction (SIGPIPE, &old_sigpipe_action, 0);
-                     report_file_error ("sending datagram",
-                                        Fcons (proc, Qnil));
-                   }
-               }
-             else
+         else
 #endif
-               {
+           {
 #ifdef HAVE_GNUTLS
-                 if (p->gnutls_p)
-                   written = emacs_gnutls_write (p, cur_buf, cur_len);
-                 else
+             if (p->gnutls_p)
+               written = emacs_gnutls_write (p, cur_buf, cur_len);
+             else
 #endif
-                   written = emacs_write (outfd, cur_buf, cur_len);
-                 rv = (written ? 0 : -1);
+               written = emacs_write (outfd, cur_buf, cur_len);
+             rv = (written ? 0 : -1);
 #ifdef ADAPTIVE_READ_BUFFERING
-                 if (p->read_output_delay > 0
-                     && p->adaptive_read_buffering == 1)
-                   {
-                     p->read_output_delay = 0;
-                     process_output_delay_count--;
-                     p->read_output_skip = 0;
-                   }
-#endif
+             if (p->read_output_delay > 0
+                 && p->adaptive_read_buffering == 1)
+               {
+                 p->read_output_delay = 0;
+                 process_output_delay_count--;
+                 p->read_output_skip = 0;
                }
-             sigaction (SIGPIPE, &old_sigpipe_action, 0);
+#endif
+           }
 
-             if (rv < 0)
-               {
-                 if (0
+         if (rv < 0)
+           {
+             if (0
 #ifdef EWOULDBLOCK
-                     || errno == EWOULDBLOCK
+                 || errno == EWOULDBLOCK
 #endif
 #ifdef EAGAIN
-                     || errno == EAGAIN
+                 || errno == EAGAIN
 #endif
-                     )
-                   /* Buffer is full.  Wait, accepting input;
-                      that may allow the program
-                      to finish doing output and read more.  */
-                   {
+                 )
+               /* Buffer is full.  Wait, accepting input;
+                  that may allow the program
+                  to finish doing output and read more.  */
+               {
 #ifdef BROKEN_PTY_READ_AFTER_EAGAIN
-                     /* A gross hack to work around a bug in FreeBSD.
-                        In the following sequence, read(2) returns
-                        bogus data:
-
-                        write(2)        1022 bytes
-                        write(2)   954 bytes, get EAGAIN
-                        read(2)   1024 bytes in process_read_output
-                        read(2)     11 bytes in process_read_output
-
-                        That is, read(2) returns more bytes than have
-                        ever been written successfully.  The 1033 bytes
-                        read are the 1022 bytes written successfully
-                        after processing (for example with CRs added if
-                        the terminal is set up that way which it is
-                        here).  The same bytes will be seen again in a
-                        later read(2), without the CRs.  */
-
-                     if (errno == EAGAIN)
-                       {
-                         int flags = FWRITE;
-                         ioctl (p->outfd, TIOCFLUSH, &flags);
-                       }
+                 /* A gross hack to work around a bug in FreeBSD.
+                    In the following sequence, read(2) returns
+                    bogus data:
+
+                    write(2)    1022 bytes
+                    write(2)   954 bytes, get EAGAIN
+                    read(2)   1024 bytes in process_read_output
+                    read(2)     11 bytes in process_read_output
+
+                    That is, read(2) returns more bytes than have
+                    ever been written successfully.  The 1033 bytes
+                    read are the 1022 bytes written successfully
+                    after processing (for example with CRs added if
+                    the terminal is set up that way which it is
+                    here).  The same bytes will be seen again in a
+                    later read(2), without the CRs.  */
+
+                 if (errno == EAGAIN)
+                   {
+                     int flags = FWRITE;
+                     ioctl (p->outfd, TIOCFLUSH, &flags);
+                   }
 #endif /* BROKEN_PTY_READ_AFTER_EAGAIN */
 
-                     /* Put what we should have written in wait_queue.  */
-                     write_queue_push (p, cur_object, cur_buf, cur_len, 1);
-                     wait_reading_process_output (0, 20 * 1000 * 1000,
-                                                  0, 0, Qnil, NULL, 0);
-                     /* Reread queue, to see what is left.  */
-                     break;
-                   }
-                 else
-                   /* This is a real error.  */
-                   report_file_error ("writing to process", Fcons (proc, Qnil));
+                 /* Put what we should have written in wait_queue.  */
+                 write_queue_push (p, cur_object, cur_buf, cur_len, 1);
+                 wait_reading_process_output (0, 20 * 1000 * 1000,
+                                              0, 0, Qnil, NULL, 0);
+                 /* Reread queue, to see what is left.  */
+                 break;
                }
-             cur_buf += written;
-             cur_len -= written;
+             else if (errno == EPIPE)
+               {
+                 p->raw_status_new = 0;
+                 pset_status (p, list2 (Qexit, make_number (256)));
+                 p->tick = ++process_tick;
+                 deactivate_process (proc);
+                 error ("process %s no longer connected to pipe; closed it",
+                        SDATA (p->name));
+               }
+             else
+               /* This is a real error.  */
+               report_file_error ("writing to process", Fcons (proc, Qnil));
            }
+         cur_buf += written;
+         cur_len -= written;
        }
-      while (!NILP (p->write_queue));
-    }
-  else
-    {
-      sigaction (SIGPIPE, &old_sigpipe_action, 0);
-      proc = process_sent_to;
-      p = XPROCESS (proc);
-      p->raw_status_new = 0;
-      pset_status (p, Fcons (Qexit, Fcons (make_number (256), Qnil)));
-      p->tick = ++process_tick;
-      deactivate_process (proc);
-      error ("SIGPIPE raised on process %s; closed it", SDATA (p->name));
     }
+  while (!NILP (p->write_queue));
 }
 
 DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
@@ -6205,39 +6113,27 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
 #ifdef SIGUSR2
       parse_signal ("usr2", SIGUSR2);
 #endif
-#ifdef SIGTERM
       parse_signal ("term", SIGTERM);
-#endif
 #ifdef SIGHUP
       parse_signal ("hup", SIGHUP);
 #endif
-#ifdef SIGINT
       parse_signal ("int", SIGINT);
-#endif
 #ifdef SIGQUIT
       parse_signal ("quit", SIGQUIT);
 #endif
-#ifdef SIGILL
       parse_signal ("ill", SIGILL);
-#endif
-#ifdef SIGABRT
       parse_signal ("abrt", SIGABRT);
-#endif
 #ifdef SIGEMT
       parse_signal ("emt", SIGEMT);
 #endif
 #ifdef SIGKILL
       parse_signal ("kill", SIGKILL);
 #endif
-#ifdef SIGFPE
       parse_signal ("fpe", SIGFPE);
-#endif
 #ifdef SIGBUS
       parse_signal ("bus", SIGBUS);
 #endif
-#ifdef SIGSEGV
       parse_signal ("segv", SIGSEGV);
-#endif
 #ifdef SIGSYS
       parse_signal ("sys", SIGSYS);
 #endif
@@ -6367,9 +6263,8 @@ process has been transmitted to the serial port.  */)
       if (!proc_encode_coding_system[new_outfd])
        proc_encode_coding_system[new_outfd]
          = xmalloc (sizeof (struct coding_system));
-      memcpy (proc_encode_coding_system[new_outfd],
-             proc_encode_coding_system[old_outfd],
-             sizeof (struct coding_system));
+      *proc_encode_coding_system[new_outfd]
+       = *proc_encode_coding_system[old_outfd];
       memset (proc_encode_coding_system[old_outfd], 0,
              sizeof (struct coding_system));
 
@@ -6403,27 +6298,15 @@ process has been transmitted to the serial port.  */)
    ** Malloc WARNING: This should never call malloc either directly or
    indirectly; if it does, that is a bug  */
 
-#ifdef SIGCHLD
-
-/* Record one child's changed status.  Return true if a child was found.  */
-static bool
-record_child_status_change (void)
+/* Record the changed status of the child process PID with wait status W.  */
+void
+record_child_status_change (pid_t pid, int w)
 {
+#ifdef SIGCHLD
   Lisp_Object proc;
   struct Lisp_Process *p;
-  pid_t pid;
-  int w;
   Lisp_Object tail;
 
-  do
-    pid = waitpid (-1, &w, WNOHANG | WUNTRACED);
-  while (pid < 0 && errno == EINTR);
-
-  /* PID == 0 means no processes found, PID == -1 means a real failure.
-     Either way, we have done all our job.  */
-  if (pid <= 0)
-    return false;
-
   /* Find the process that signaled us, and record its status.  */
 
   /* The process can have been deleted by Fdelete_process.  */
@@ -6434,7 +6317,7 @@ record_child_status_change (void)
          || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid)))
        {
          XSETCAR (tail, Qnil);
-         return true;
+         return;
        }
     }
 
@@ -6504,10 +6387,11 @@ record_child_status_change (void)
       if (input_available_clear_time)
        *input_available_clear_time = make_emacs_time (0, 0);
     }
-
-  return true;
+#endif
 }
 
+#ifdef SIGCHLD
+
 /* On some systems, the SIGCHLD handler must return right away.  If
    any more processes want to signal us, we will get another signal.
    Otherwise, loop around to use up all the processes that have
@@ -6523,14 +6407,29 @@ enum { CAN_HANDLE_MULTIPLE_CHILDREN = 1 };
 static void
 handle_child_signal (int sig)
 {
-  while (record_child_status_change () && CAN_HANDLE_MULTIPLE_CHILDREN)
-    continue;
+  do
+    {
+      pid_t pid;
+      int status;
+
+      do
+       pid = waitpid (-1, &status, WNOHANG | WUNTRACED);
+      while (pid < 0 && errno == EINTR);
+
+      /* PID == 0 means no processes found, PID == -1 means a real failure.
+        Either way, we have done all our job.  */
+      if (pid <= 0)
+       break;
+
+      record_child_status_change (pid, status);
+    }
+  while (CAN_HANDLE_MULTIPLE_CHILDREN);
 }
 
 static void
 deliver_child_signal (int sig)
 {
-  handle_on_main_thread (sig, handle_child_signal);
+  deliver_process_signal (sig, handle_child_signal);
 }
 
 #endif /* SIGCHLD */
@@ -6854,7 +6753,7 @@ delete_gpm_wait_descriptor (int desc)
 
 # endif
 
-# ifdef SIGIO
+# ifdef USABLE_SIGIO
 
 /* Return nonzero if *MASK has a bit set
    that corresponds to one of the keyboard input descriptors.  */
@@ -6904,14 +6803,14 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
    see full version for other parameters. We know that wait_proc will
      always be NULL, since `subprocesses' isn't defined.
 
-   DO_DISPLAY != 0 means redisplay should be done to show subprocess
+   DO_DISPLAY means redisplay should be done to show subprocess
    output that arrives.
 
    Return true if we received input from any process.  */
 
 int
 wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
-                            int do_display,
+                            bool do_display,
                             Lisp_Object wait_for_cell,
                             struct Lisp_Process *wait_proc, int just_wait_proc)
 {
@@ -6987,7 +6886,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
          do
            {
-             int old_timers_run = timers_run;
+             unsigned old_timers_run = timers_run;
              timer_delay = timer_check ();
              if (timers_run != old_timers_run && do_display)
                /* We must retry, since a timer may have requeued itself