Assume POSIX 1003.1-1988 or later for signal.h.
[bpt/emacs.git] / src / sysdep.c
index d9e239d..5291c5d 100644 (file)
@@ -21,10 +21,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #define SYSTIME_INLINE EXTERN_INLINE
 
-#include <ctype.h>
-#include <signal.h>
+#include <execinfo.h>
 #include <stdio.h>
-#include <setjmp.h>
 #ifdef HAVE_PWD_H
 #include <pwd.h>
 #include <grp.h>
@@ -33,6 +31,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <unistd.h>
 
 #include <allocator.h>
+#include <c-ctype.h>
 #include <careadlinkat.h>
 #include <ignore-value.h>
 #include <utimens.h>
@@ -55,6 +54,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifdef WINDOWSNT
 #define read sys_read
 #define write sys_write
+#ifndef STDERR_FILENO
+#define STDERR_FILENO fileno(GetStdHandle(STD_ERROR_HANDLE))
+#endif
 #include <windows.h>
 #endif /* not WINDOWSNT */
 
@@ -99,7 +101,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define _P_WAIT 0
 int _cdecl _spawnlp (int, const char *, const char *, ...);
 int _cdecl _getpid (void);
-extern char *getwd (char *);
 #endif
 
 #include "syssignal.h"
@@ -107,9 +108,6 @@ extern char *getwd (char *);
 
 static int emacs_get_tty (int, struct emacs_tty *);
 static int emacs_set_tty (int, struct emacs_tty *, int);
-#if defined TIOCNOTTY || defined USG5 || defined CYGWIN
-static _Noreturn void croak (char *);
-#endif
 
 /* ULLONG_MAX is missing on Red Hat Linux 7.3; see Bug#11781.  */
 #ifndef ULLONG_MAX
@@ -135,12 +133,12 @@ char*
 get_current_dir_name (void)
 {
   char *buf;
-  char *pwd;
+  char *pwd = getenv ("PWD");
   struct stat dotstat, pwdstat;
-  /* If PWD is accurate, use it instead of calling getwd.  PWD is
+  /* If PWD is accurate, use it instead of calling getcwd.  PWD is
      sometimes a nicer name, and using it may avoid a fatal error if a
      parent directory is searchable but not readable.  */
-    if ((pwd = getenv ("PWD")) != 0
+  if (pwd
       && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
       && stat (pwd, &pwdstat) == 0
       && stat (".", &dotstat) == 0
@@ -156,7 +154,6 @@ get_current_dir_name (void)
         return NULL;
       strcpy (buf, pwd);
     }
-#ifdef HAVE_GETCWD
   else
     {
       size_t buf_size = 1024;
@@ -180,22 +177,6 @@ get_current_dir_name (void)
             return NULL;
         }
     }
-#else
-  else
-    {
-      /* We need MAXPATHLEN here.  */
-      buf = malloc (MAXPATHLEN + 1);
-      if (!buf)
-        return NULL;
-      if (getwd (buf) == NULL)
-        {
-          int tmp_errno = errno;
-          free (buf);
-          errno = tmp_errno;
-          return NULL;
-        }
-    }
-#endif
   return buf;
 }
 #endif
@@ -283,71 +264,76 @@ init_baud_rate (int fd)
 
 \f
 
-/* Set nonzero to make following function work under dbx
-   (at least for bsd).  */
-int wait_debugging EXTERNALLY_VISIBLE;
-
 #ifndef MSDOS
 
-static void
-wait_for_termination_1 (pid_t pid, int interruptible)
+/* Wait for the subprocess with process id CHILD to terminate or change status.
+   CHILD must be a child process that has not been reaped.
+   If STATUS is non-null, store the waitpid-style exit status into *STATUS
+   and tell wait_reading_process_output that it needs to look around.
+   Use waitpid-style OPTIONS when waiting.
+   If INTERRUPTIBLE, this function is interruptible by a signal.
+
+   Return CHILD if successful, 0 if no status is available;
+   the latter is possible only when options & NOHANG.  */
+static pid_t
+get_child_status (pid_t child, int *status, int options, bool interruptible)
 {
-  while (1)
-    {
-#if (defined (BSD_SYSTEM) || defined (HPUX)) && !defined (__GNU__)
-      /* Note that kill returns -1 even if the process is just a zombie now.
-        But inevitably a SIGCHLD interrupt should be generated
-        and child_sig will do waitpid and make the process go away.  */
-      /* There is some indication that there is a bug involved with
-        termination of subprocesses, perhaps involving a kernel bug too,
-        but no idea what it is.  Just as a hunch we signal SIGCHLD to see
-        if that causes the problem to go away or get worse.  */
-      sigsetmask (sigmask (SIGCHLD));
-      if (0 > kill (pid, 0))
-       {
-         sigsetmask (SIGEMPTYMASK);
-         kill (getpid (), SIGCHLD);
-         break;
-       }
-      if (wait_debugging)
-       sleep (1);
-      else
-       sigpause (SIGEMPTYMASK);
-#else /* not BSD_SYSTEM, and not HPUX version >= 6 */
-#ifdef WINDOWSNT
-      wait (0);
-      break;
-#else /* not WINDOWSNT */
-      sigblock (sigmask (SIGCHLD));
-      errno = 0;
-      if (kill (pid, 0) == -1 && errno == ESRCH)
-       {
-         sigunblock (sigmask (SIGCHLD));
-         break;
-       }
+  pid_t pid;
 
-      sigsuspend (&empty_mask);
-#endif /* not WINDOWSNT */
-#endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
+  /* Invoke waitpid only with a known process ID; do not invoke
+     waitpid with a nonpositive argument.  Otherwise, Emacs might
+     reap an unwanted process by mistake.  For example, invoking
+     waitpid (-1, ...) can mess up glib by reaping glib's subprocesses,
+     so that another thread running glib won't find them.  */
+  eassert (0 < child);
+
+  while ((pid = waitpid (child, status, options)) < 0)
+    {
+      /* Check that CHILD is a child process that has not been reaped,
+        and that STATUS and OPTIONS are valid.  Otherwise abort,
+        as continuing after this internal error could cause Emacs to
+        become confused and kill innocent-victim processes.  */
+      if (errno != EINTR)
+       emacs_abort ();
+
+      /* Note: the MS-Windows emulation of waitpid calls QUIT
+        internally.  */
       if (interruptible)
        QUIT;
     }
-}
 
-/* Wait for subprocess with process id `pid' to terminate and
-   make sure it will get eliminated (not remain forever as a zombie) */
+  /* If successful and status is requested, tell wait_reading_process_output
+     that it needs to wake up and look around.  */
+  if (pid && status && input_available_clear_time)
+    *input_available_clear_time = make_emacs_time (0, 0);
 
+  return pid;
+}
+
+/* Wait for the subprocess with process id CHILD to terminate.
+   CHILD must be a child process that has not been reaped.
+   If STATUS is non-null, store the waitpid-style exit status into *STATUS
+   and tell wait_reading_process_output that it needs to look around.
+   If INTERRUPTIBLE, this function is interruptible by a signal.  */
 void
-wait_for_termination (pid_t pid)
+wait_for_termination (pid_t child, int *status, bool interruptible)
 {
-  wait_for_termination_1 (pid, 0);
+  get_child_status (child, status, 0, interruptible);
 }
 
-/* Like the above, but allow keyboard interruption. */
-void
-interruptible_wait_for_termination (pid_t pid)
+/* Report whether the subprocess with process id CHILD has changed status.
+   Termination counts as a change of status.
+   CHILD must be a child process that has not been reaped.
+   If STATUS is non-null, store the waitpid-style exit status into *STATUS
+   and tell wait_reading_process_output that it needs to look around.
+   Use waitpid-style OPTIONS to check status, but do not wait.
+
+   Return CHILD if successful, 0 if no status is available because
+   the process's state has not changed.  */
+pid_t
+child_status_changed (pid_t child, int *status, int options)
 {
-  wait_for_termination_1 (pid, 1);
+  return get_child_status (child, status, WNOHANG | options, 0);
 }
 
 /*
@@ -456,11 +442,11 @@ child_setup_tty (int out)
 #endif /* not MSDOS */
 
 \f
-/* Record a signal code and the handler for it.  */
+/* Record a signal code and the action for it.  */
 struct save_signal
 {
   int code;
-  void (*handler) (int);
+  struct sigaction action;
 };
 
 static void save_signal_handlers (struct save_signal *);
@@ -471,20 +457,15 @@ static void restore_signal_handlers (struct save_signal *);
 void
 sys_suspend (void)
 {
-#if defined (SIGTSTP) && !defined (MSDOS)
-
-  {
-    int pgrp = EMACS_GETPGRP (0);
-    EMACS_KILLPG (pgrp, SIGTSTP);
-  }
-
-#else /* No SIGTSTP */
+#ifndef DOS_NT
+  kill (0, SIGTSTP);
+#else
 /* On a system where suspending is not implemented,
    instead fork a subshell and let it talk directly to the terminal
    while we wait.  */
   sys_subshell ();
 
-#endif /* no SIGTSTP */
+#endif
 }
 
 /* Fork a subshell.  */
@@ -496,7 +477,8 @@ sys_subshell (void)
   int st;
   char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS.  */
 #endif
-  int pid;
+  pid_t pid;
+  int status;
   struct save_signal saved_handlers[5];
   Lisp_Object dir;
   unsigned char *volatile str_volatile = 0;
@@ -506,7 +488,7 @@ sys_subshell (void)
   saved_handlers[0].code = SIGINT;
   saved_handlers[1].code = SIGQUIT;
   saved_handlers[2].code = SIGTERM;
-#ifdef SIGIO
+#ifdef USABLE_SIGIO
   saved_handlers[3].code = SIGIO;
   saved_handlers[4].code = 0;
 #else
@@ -534,7 +516,6 @@ sys_subshell (void)
 #ifdef DOS_NT
   pid = 0;
   save_signal_handlers (saved_handlers);
-  synch_process_alive = 1;
 #else
   pid = vfork ();
   if (pid == -1)
@@ -546,7 +527,7 @@ sys_subshell (void)
       const char *sh = 0;
 
 #ifdef DOS_NT    /* MW, Aug 1993 */
-      getwd (oldwd);
+      getcwd (oldwd, sizeof oldwd);
       if (sh == 0)
        sh = (char *) egetenv ("SUSPEND");      /* KFS, 1994-12-14 */
 #endif
@@ -603,14 +584,12 @@ sys_subshell (void)
   /* Do this now if we did not do it before.  */
 #ifndef MSDOS
   save_signal_handlers (saved_handlers);
-  synch_process_alive = 1;
 #endif
 
 #ifndef DOS_NT
-  wait_for_termination (pid);
+  wait_for_termination (pid, &status, 0);
 #endif
   restore_signal_handlers (saved_handlers);
-  synch_process_alive = 0;
 }
 
 static void
@@ -618,8 +597,9 @@ save_signal_handlers (struct save_signal *saved_handlers)
 {
   while (saved_handlers->code)
     {
-      saved_handlers->handler
-        = (void (*) (int)) signal (saved_handlers->code, SIG_IGN);
+      struct sigaction action;
+      emacs_sigaction_init (&action, SIG_IGN);
+      sigaction (saved_handlers->code, &action, &saved_handlers->action);
       saved_handlers++;
     }
 }
@@ -629,118 +609,149 @@ restore_signal_handlers (struct save_signal *saved_handlers)
 {
   while (saved_handlers->code)
     {
-      signal (saved_handlers->code, saved_handlers->handler);
+      sigaction (saved_handlers->code, &saved_handlers->action, 0);
       saved_handlers++;
     }
 }
 \f
-#ifndef SIGIO
-/* If SIGIO is broken, don't do anything. */
-void
-init_sigio (int fd)
-{
-}
-
-static void
-reset_sigio (int fd)
-{
-}
-
-void
-request_sigio (void)
-{
-}
-
-void
-unrequest_sigio (void)
-{
-}
-
-#else
-#ifdef F_SETFL
-
+#ifdef USABLE_SIGIO
 static int old_fcntl_flags[MAXDESC];
+#endif
 
 void
 init_sigio (int fd)
 {
-#ifdef FASYNC
+#ifdef USABLE_SIGIO
   old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
   fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
-#endif
   interrupts_deferred = 0;
+#endif
 }
 
 static void
 reset_sigio (int fd)
 {
-#ifdef FASYNC
+#ifdef USABLE_SIGIO
   fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
 #endif
 }
 
-#ifdef FASYNC          /* F_SETFL does not imply existence of FASYNC */
-/* XXX Uhm, FASYNC is not used anymore here. */
-/* XXX Yeah, but you need it for SIGIO, don't you? */
-
 void
 request_sigio (void)
 {
+#ifdef USABLE_SIGIO
+  sigset_t unblocked;
+
   if (noninteractive)
     return;
 
-#ifdef SIGWINCH
-  sigunblock (sigmask (SIGWINCH));
-#endif
-  sigunblock (sigmask (SIGIO));
+  sigemptyset (&unblocked);
+# ifdef SIGWINCH
+  sigaddset (&unblocked, SIGWINCH);
+# endif
+  sigaddset (&unblocked, SIGIO);
+  pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
 
   interrupts_deferred = 0;
+#endif
 }
 
 void
 unrequest_sigio (void)
 {
+#ifdef USABLE_SIGIO
+  sigset_t blocked;
+
   if (noninteractive)
     return;
 
-#if 0 /* XXX What's wrong with blocking SIGIO under X?  */
-  if (x_display_list)
-    return;
+  sigemptyset (&blocked);
+# ifdef SIGWINCH
+  sigaddset (&blocked, SIGWINCH);
+# endif
+  sigaddset (&blocked, SIGIO);
+  pthread_sigmask (SIG_BLOCK, &blocked, 0);
+  interrupts_deferred = 1;
 #endif
+}
 
-#ifdef SIGWINCH
-  sigblock (sigmask (SIGWINCH));
+void
+ignore_sigio (void)
+{
+#ifdef USABLE_SIGIO
+  signal (SIGIO, SIG_IGN);
 #endif
-  sigblock (sigmask (SIGIO));
-  interrupts_deferred = 1;
 }
 
-#else /* no FASYNC */
-#ifndef MSDOS
+\f
+/* Saving and restoring the process group of Emacs's terminal.  */
 
-void
-request_sigio (void)
-{
-  if (noninteractive || read_socket_hook)
-    return;
+/* The process group of which Emacs was a member when it initially
+   started.
 
-  croak ("request_sigio");
-}
+   If Emacs was in its own process group (i.e. inherited_pgroup ==
+   getpid ()), then we know we're running under a shell with job
+   control (Emacs would never be run as part of a pipeline).
+   Everything is fine.
+
+   If Emacs was not in its own process group, then we know we're
+   running under a shell (or a caller) that doesn't know how to
+   separate itself from Emacs (like sh).  Emacs must be in its own
+   process group in order to receive SIGIO correctly.  In this
+   situation, we put ourselves in our own pgroup, forcibly set the
+   tty's pgroup to our pgroup, and make sure to restore and reinstate
+   the tty's pgroup just like any other terminal setting.  If
+   inherited_group was not the tty's pgroup, then we'll get a
+   SIGTTmumble when we try to change the tty's pgroup, and a CONT if
+   it goes foreground in the future, which is what should happen.  */
+
+static pid_t inherited_pgroup;
 
 void
-unrequest_sigio (void)
+init_foreground_group (void)
 {
-  if (noninteractive || read_socket_hook)
-    return;
+  pid_t pgrp = getpgrp ();
+  inherited_pgroup = getpid () == pgrp ? 0 : pgrp;
+}
+
+/* Safely set a controlling terminal FD's process group to PGID.
+   If we are not in the foreground already, POSIX requires tcsetpgrp
+   to deliver a SIGTTOU signal, which would stop us.  This is an
+   annoyance, so temporarily ignore the signal.
 
-  croak ("unrequest_sigio");
+   In practice, platforms lacking SIGTTOU also lack tcsetpgrp, so
+   skip all this unless SIGTTOU is defined.  */
+static void
+tcsetpgrp_without_stopping (int fd, pid_t pgid)
+{
+#ifdef SIGTTOU
+  signal_handler_t handler;
+  block_input ();
+  handler = signal (SIGTTOU, SIG_IGN);
+  tcsetpgrp (fd, pgid);
+  signal (SIGTTOU, handler);
+  unblock_input ();
+#endif
 }
 
-#endif /* MSDOS */
-#endif /* FASYNC */
-#endif /* F_SETFL */
-#endif /* SIGIO */
+/* Split off the foreground process group to Emacs alone.  When we are
+   in the foreground, but not started in our own process group,
+   redirect the tty device handle FD to point to our own process
+   group.  FD must be the file descriptor of the controlling tty.  */
+static void
+narrow_foreground_group (int fd)
+{
+  if (inherited_pgroup && setpgid (0, 0) == 0)
+    tcsetpgrp_without_stopping (fd, getpid ());
+}
 
+/* Set the tty to our original foreground group.  */
+static void
+widen_foreground_group (int fd)
+{
+  if (inherited_pgroup && setpgid (0, inherited_pgroup) == 0)
+    tcsetpgrp_without_stopping (fd, inherited_pgroup);
+}
 \f
 /* Getting and setting emacs_tty structures.  */
 
@@ -858,6 +869,8 @@ init_sys_modes (struct tty_display_info *tty_out)
   if (!tty_out->output)
     return;                     /* The tty is suspended. */
 
+  narrow_foreground_group (fileno (tty_out->input));
+
   if (! tty_out->old_tty)
     tty_out->old_tty = xmalloc (sizeof *tty_out->old_tty);
 
@@ -1027,8 +1040,7 @@ init_sys_modes (struct tty_display_info *tty_out)
 #endif
 #endif
 
-#ifdef F_SETFL
-#ifdef F_GETOWN                /* F_SETFL does not imply existence of F_GETOWN */
+#ifdef F_GETOWN
   if (interrupt_input)
     {
       old_fcntl_owner[fileno (tty_out->input)] =
@@ -1046,7 +1058,6 @@ init_sys_modes (struct tty_display_info *tty_out)
 #endif /* HAVE_GPM */
     }
 #endif /* F_GETOWN */
-#endif /* F_SETFL */
 
 #ifdef _IOFBF
   /* This symbol is defined on recent USG systems.
@@ -1266,8 +1277,8 @@ reset_sys_modes (struct tty_display_info *tty_out)
   fsync (fileno (tty_out->output));
 #endif
 
-#ifdef F_SETFL
-#ifdef F_SETOWN                /* F_SETFL does not imply existence of F_SETOWN */
+#ifndef DOS_NT
+#ifdef F_SETOWN
   if (interrupt_input)
     {
       reset_sigio (fileno (tty_out->input));
@@ -1275,11 +1286,9 @@ reset_sys_modes (struct tty_display_info *tty_out)
              old_fcntl_owner[fileno (tty_out->input)]);
     }
 #endif /* F_SETOWN */
-#ifdef O_NDELAY
   fcntl (fileno (tty_out->input), F_SETFL,
-         fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY);
+         fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NONBLOCK);
 #endif
-#endif /* F_SETFL */
 
   if (tty_out->old_tty)
     while (emacs_set_tty (fileno (tty_out->input),
@@ -1290,6 +1299,7 @@ reset_sys_modes (struct tty_display_info *tty_out)
   dos_ttcooked ();
 #endif
 
+  widen_foreground_group (fileno (tty_out->input));
 }
 \f
 #ifdef HAVE_PTYS
@@ -1470,121 +1480,224 @@ init_system_name (void)
   }
 }
 \f
-/* POSIX signals support - DJB */
-/* Anyone with POSIX signals should have ANSI C declarations */
-
 sigset_t empty_mask;
 
-#ifndef WINDOWSNT
+static struct sigaction process_fatal_action;
 
-signal_handler_t
-sys_signal (int signal_number, signal_handler_t action)
-{
-  struct sigaction new_action, old_action;
-  sigemptyset (&new_action.sa_mask);
-  new_action.sa_handler = action;
-  new_action.sa_flags = 0;
-#if defined (SA_RESTART)
-  /* Emacs mostly works better with restartable system services. If this
-     flag exists, we probably want to turn it on here.
-     However, on some systems (only hpux11 at present) this resets the
-     timeout of `select' which means that `select' never finishes if
-     it keeps getting signals.
-     We define BROKEN_SA_RESTART on those systems.  */
-  /* It's not clear why the comment above says "mostly works better".  --Stef
-     When SYNC_INPUT is set, we don't want SA_RESTART because we need to poll
+static int
+emacs_sigaction_flags (void)
+{
+#ifdef SA_RESTART
+  /* SA_RESTART causes interruptible functions with timeouts (e.g.,
+     'select') to reset their timeout on some platforms (e.g.,
+     HP-UX 11), which is not what we want.  Also, when Emacs is
+     interactive, we don't want SA_RESTART because we need to poll
      for pending input so we need long-running syscalls to be interrupted
-     after a signal that sets the interrupt_input_pending flag.  */
-  /* Non-interactive keyboard input goes through stdio, where we always
-     want restartable system calls.  */
-# if defined (BROKEN_SA_RESTART) || defined (SYNC_INPUT)
+     after a signal that sets pending_signals.
+
+     Non-interactive keyboard input goes through stdio, where we
+     always want restartable system calls.  */
   if (noninteractive)
-# endif
-    new_action.sa_flags = SA_RESTART;
+    return SA_RESTART;
 #endif
-  sigaction (signal_number, &new_action, &old_action);
-  return (old_action.sa_handler);
+  return 0;
 }
 
-#endif /* WINDOWSNT */
+/* Store into *ACTION a signal action suitable for Emacs, with handler
+   HANDLER.  */
+void
+emacs_sigaction_init (struct sigaction *action, signal_handler_t handler)
+{
+  sigemptyset (&action->sa_mask);
+
+  /* When handling a signal, block nonfatal system signals that are caught
+     by Emacs.  This makes race conditions less likely.  */
+  sigaddset (&action->sa_mask, SIGALRM);
+  sigaddset (&action->sa_mask, SIGCHLD);
+#ifdef SIGDANGER
+  sigaddset (&action->sa_mask, SIGDANGER);
+#endif
+#ifdef PROFILER_CPU_SUPPORT
+  sigaddset (&action->sa_mask, SIGPROF);
+#endif
+#ifdef SIGWINCH
+  sigaddset (&action->sa_mask, SIGWINCH);
+#endif
+  if (! noninteractive)
+    {
+      sigaddset (&action->sa_mask, SIGINT);
+      sigaddset (&action->sa_mask, SIGQUIT);
+#ifdef USABLE_SIGIO
+      sigaddset (&action->sa_mask, SIGIO);
+#endif
+    }
+
+  if (! IEEE_FLOATING_POINT)
+    sigaddset (&action->sa_mask, SIGFPE);
+
+  action->sa_handler = handler;
+  action->sa_flags = emacs_sigaction_flags ();
+}
 
-#ifndef __GNUC__
-/* If we're compiling with GCC, we don't need this function, since it
-   can be written as a macro.  */
-sigset_t
-sys_sigmask (int sig)
+#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
+static pthread_t main_thread;
+#endif
+
+/* SIG has arrived at the current process.  Deliver it to the main
+   thread, which should handle it with HANDLER.
+
+   If we are on the main thread, handle the signal SIG with HANDLER.
+   Otherwise, redirect the signal to the main thread, blocking it from
+   this thread.  POSIX says any thread can receive a signal that is
+   associated with a process, process group, or asynchronous event.
+   On GNU/Linux that is not true, but for other systems (FreeBSD at
+   least) it is.  */
+void
+deliver_process_signal (int sig, signal_handler_t handler)
 {
-  sigset_t mask;
-  sigemptyset (&mask);
-  sigaddset (&mask, sig);
-  return mask;
+  /* Preserve errno, to avoid race conditions with signal handlers that
+     might change errno.  Races can occur even in single-threaded hosts.  */
+  int old_errno = errno;
+
+  bool on_main_thread = true;
+#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
+  if (! pthread_equal (pthread_self (), main_thread))
+    {
+      sigset_t blocked;
+      sigemptyset (&blocked);
+      sigaddset (&blocked, sig);
+      pthread_sigmask (SIG_BLOCK, &blocked, 0);
+      pthread_kill (main_thread, sig);
+      on_main_thread = false;
+    }
+#endif
+  if (on_main_thread)
+    handler (sig);
+
+  errno = old_errno;
 }
+
+/* Static location to save a fatal backtrace in a thread.
+   FIXME: If two subsidiary threads fail simultaneously, the resulting
+   backtrace may be garbage.  */
+enum { BACKTRACE_LIMIT_MAX = 500 };
+static void *thread_backtrace_buffer[BACKTRACE_LIMIT_MAX + 1];
+static int thread_backtrace_npointers;
+
+/* SIG has arrived at the current thread.
+   If we are on the main thread, handle the signal SIG with HANDLER.
+   Otherwise, this is a fatal error in the handling thread.  */
+static void
+deliver_thread_signal (int sig, signal_handler_t handler)
+{
+  int old_errno = errno;
+
+#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
+  if (! pthread_equal (pthread_self (), main_thread))
+    {
+      thread_backtrace_npointers
+       = backtrace (thread_backtrace_buffer, BACKTRACE_LIMIT_MAX);
+      sigaction (sig, &process_fatal_action, 0);
+      pthread_kill (main_thread, sig);
+
+      /* Avoid further damage while the main thread is exiting.  */
+      while (1)
+       sigsuspend (&empty_mask);
+    }
 #endif
 
-/* I'd like to have these guys return pointers to the mask storage in here,
-   but there'd be trouble if the code was saving multiple masks.  I'll be
-   safe and pass the structure.  It normally won't be more than 2 bytes
-   anyhow. - DJB */
+  handler (sig);
+  errno = old_errno;
+}
+\f
+#if !HAVE_DECL_SYS_SIGLIST
+# undef sys_siglist
+# ifdef _sys_siglist
+#  define sys_siglist _sys_siglist
+# else
+#  define sys_siglist my_sys_siglist
+static char const *sys_siglist[NSIG];
+# endif
+#endif
+
+#ifdef _sys_nsig
+# define sys_siglist_entries _sys_nsig
+#else
+# define sys_siglist_entries NSIG
+#endif
+
+/* Handle bus errors, invalid instruction, etc.  */
+static void
+handle_fatal_signal (int sig)
+{
+  terminate_due_to_signal (sig, 40);
+}
 
-sigset_t
-sys_sigblock (sigset_t new_mask)
+static void
+deliver_fatal_signal (int sig)
 {
-  sigset_t old_mask;
-  pthread_sigmask (SIG_BLOCK, &new_mask, &old_mask);
-  return (old_mask);
+  deliver_process_signal (sig, handle_fatal_signal);
 }
 
-sigset_t
-sys_sigunblock (sigset_t new_mask)
+static void
+deliver_fatal_thread_signal (int sig)
 {
-  sigset_t old_mask;
-  pthread_sigmask (SIG_UNBLOCK, &new_mask, &old_mask);
-  return (old_mask);
+  deliver_thread_signal (sig, handle_fatal_signal);
 }
 
-sigset_t
-sys_sigsetmask (sigset_t new_mask)
+static _Noreturn void
+handle_arith_signal (int sig)
 {
-  sigset_t old_mask;
-  pthread_sigmask (SIG_SETMASK, &new_mask, &old_mask);
-  return (old_mask);
+  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+  xsignal0 (Qarith_error);
 }
 
-\f
-#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
-static char *my_sys_siglist[NSIG];
-# ifdef sys_siglist
-#  undef sys_siglist
-# endif
-# define sys_siglist my_sys_siglist
-#endif
+static void
+deliver_arith_signal (int sig)
+{
+  deliver_thread_signal (sig, handle_arith_signal);
+}
+
+/* Treat SIG as a terminating signal, unless it is already ignored and
+   we are in --batch mode.  Among other things, this makes nohup work.  */
+static void
+maybe_fatal_sig (int sig)
+{
+  bool catch_sig = !noninteractive;
+  if (!catch_sig)
+    {
+      struct sigaction old_action;
+      sigaction (sig, 0, &old_action);
+      catch_sig = old_action.sa_handler != SIG_IGN;
+    }
+  if (catch_sig)
+    sigaction (sig, &process_fatal_action, 0);
+}
 
 void
-init_signals (void)
+init_signals (bool dumping)
 {
+  struct sigaction thread_fatal_action;
+  struct sigaction action;
+
   sigemptyset (&empty_mask);
 
-#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
+#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
+  main_thread = pthread_self ();
+#endif
+
+#if !HAVE_DECL_SYS_SIGLIST && !defined _sys_siglist
   if (! initialized)
     {
-# ifdef SIGABRT
       sys_siglist[SIGABRT] = "Aborted";
-# endif
 # ifdef SIGAIO
       sys_siglist[SIGAIO] = "LAN I/O interrupt";
 # endif
-# ifdef SIGALRM
       sys_siglist[SIGALRM] = "Alarm clock";
-# endif
 # ifdef SIGBUS
       sys_siglist[SIGBUS] = "Bus error";
 # endif
-# ifdef SIGCLD
-      sys_siglist[SIGCLD] = "Child status changed";
-# endif
-# ifdef SIGCHLD
       sys_siglist[SIGCHLD] = "Child status changed";
-# endif
 # ifdef SIGCONT
       sys_siglist[SIGCONT] = "Continued";
 # endif
@@ -1597,24 +1710,16 @@ init_signals (void)
 # ifdef SIGEMT
       sys_siglist[SIGEMT] = "Emulation trap";
 # endif
-# ifdef SIGFPE
       sys_siglist[SIGFPE] = "Arithmetic exception";
-# endif
 # ifdef SIGFREEZE
       sys_siglist[SIGFREEZE] = "SIGFREEZE";
 # endif
 # ifdef SIGGRANT
       sys_siglist[SIGGRANT] = "Monitor mode granted";
 # endif
-# ifdef SIGHUP
       sys_siglist[SIGHUP] = "Hangup";
-# endif
-# ifdef SIGILL
       sys_siglist[SIGILL] = "Illegal instruction";
-# endif
-# ifdef SIGINT
       sys_siglist[SIGINT] = "Interrupt";
-# endif
 # ifdef SIGIO
       sys_siglist[SIGIO] = "I/O possible";
 # endif
@@ -1624,9 +1729,7 @@ init_signals (void)
 # ifdef SIGIOT
       sys_siglist[SIGIOT] = "IOT trap";
 # endif
-# ifdef SIGKILL
       sys_siglist[SIGKILL] = "Killed";
-# endif
 # ifdef SIGLOST
       sys_siglist[SIGLOST] = "Resource lost";
 # endif
@@ -1639,9 +1742,7 @@ init_signals (void)
 # ifdef SIGPHONE
       sys_siglist[SIGWIND] = "SIGPHONE";
 # endif
-# ifdef SIGPIPE
       sys_siglist[SIGPIPE] = "Broken pipe";
-# endif
 # ifdef SIGPOLL
       sys_siglist[SIGPOLL] = "Pollable event occurred";
 # endif
@@ -1654,18 +1755,14 @@ init_signals (void)
 # ifdef SIGPWR
       sys_siglist[SIGPWR] = "Power-fail restart";
 # endif
-# ifdef SIGQUIT
       sys_siglist[SIGQUIT] = "Quit";
-# endif
 # ifdef SIGRETRACT
       sys_siglist[SIGRETRACT] = "Need to relinquish monitor mode";
 # endif
 # ifdef SIGSAK
       sys_siglist[SIGSAK] = "Secure attention";
 # endif
-# ifdef SIGSEGV
       sys_siglist[SIGSEGV] = "Segmentation violation";
-# endif
 # ifdef SIGSOUND
       sys_siglist[SIGSOUND] = "Sound completed";
 # endif
@@ -1678,9 +1775,7 @@ init_signals (void)
 # ifdef SIGSYS
       sys_siglist[SIGSYS] = "Bad argument to system call";
 # endif
-# ifdef SIGTERM
       sys_siglist[SIGTERM] = "Terminated";
-# endif
 # ifdef SIGTHAW
       sys_siglist[SIGTHAW] = "SIGTHAW";
 # endif
@@ -1724,7 +1819,130 @@ init_signals (void)
       sys_siglist[SIGXFSZ] = "File size limit exceeded";
 # endif
     }
-#endif /* !defined HAVE_STRSIGNAL && !defined HAVE_DECL_SYS_SIGLIST */
+#endif /* !HAVE_DECL_SYS_SIGLIST && !_sys_siglist */
+
+  /* Don't alter signal handlers if dumping.  On some machines,
+     changing signal handlers sets static data that would make signals
+     fail to work right when the dumped Emacs is run.  */
+  if (dumping)
+    return;
+
+  sigfillset (&process_fatal_action.sa_mask);
+  process_fatal_action.sa_handler = deliver_fatal_signal;
+  process_fatal_action.sa_flags = emacs_sigaction_flags ();
+
+  sigfillset (&thread_fatal_action.sa_mask);
+  thread_fatal_action.sa_handler = deliver_fatal_thread_signal;
+  thread_fatal_action.sa_flags = process_fatal_action.sa_flags;
+
+  /* SIGINT may need special treatment on MS-Windows.  See
+     http://lists.gnu.org/archive/html/emacs-devel/2010-09/msg01062.html
+     Please update the doc of kill-emacs, kill-emacs-hook, and
+     NEWS if you change this.  */
+
+  maybe_fatal_sig (SIGHUP);
+  maybe_fatal_sig (SIGINT);
+  maybe_fatal_sig (SIGTERM);
+
+  /* Emacs checks for write errors, so it can safely ignore SIGPIPE.
+     However, in batch mode leave SIGPIPE alone, as that causes Emacs
+     to behave more like typical batch applications do.  */
+  if (! noninteractive)
+    signal (SIGPIPE, SIG_IGN);
+
+  sigaction (SIGQUIT, &process_fatal_action, 0);
+  sigaction (SIGILL, &thread_fatal_action, 0);
+  sigaction (SIGTRAP, &thread_fatal_action, 0);
+
+  /* Typically SIGFPE is thread-specific and is fatal, like SIGILL.
+     But on a non-IEEE host SIGFPE can come from a trap in the Lisp
+     interpreter's floating point operations, so treat SIGFPE as an
+     arith-error if it arises in the main thread.  */
+  if (IEEE_FLOATING_POINT)
+    sigaction (SIGFPE, &thread_fatal_action, 0);
+  else
+    {
+      emacs_sigaction_init (&action, deliver_arith_signal);
+      sigaction (SIGFPE, &action, 0);
+    }
+
+#ifdef SIGUSR1
+  add_user_signal (SIGUSR1, "sigusr1");
+#endif
+#ifdef SIGUSR2
+  add_user_signal (SIGUSR2, "sigusr2");
+#endif
+  sigaction (SIGABRT, &thread_fatal_action, 0);
+#ifdef SIGPRE
+  sigaction (SIGPRE, &thread_fatal_action, 0);
+#endif
+#ifdef SIGORE
+  sigaction (SIGORE, &thread_fatal_action, 0);
+#endif
+#ifdef SIGUME
+  sigaction (SIGUME, &thread_fatal_action, 0);
+#endif
+#ifdef SIGDLK
+  sigaction (SIGDLK, &process_fatal_action, 0);
+#endif
+#ifdef SIGCPULIM
+  sigaction (SIGCPULIM, &process_fatal_action, 0);
+#endif
+#ifdef SIGIOT
+  sigaction (SIGIOT, &thread_fatal_action, 0);
+#endif
+#ifdef SIGEMT
+  sigaction (SIGEMT, &thread_fatal_action, 0);
+#endif
+#ifdef SIGBUS
+  sigaction (SIGBUS, &thread_fatal_action, 0);
+#endif
+  sigaction (SIGSEGV, &thread_fatal_action, 0);
+#ifdef SIGSYS
+  sigaction (SIGSYS, &thread_fatal_action, 0);
+#endif
+  sigaction (SIGTERM, &process_fatal_action, 0);
+#ifdef SIGPROF
+  signal (SIGPROF, SIG_IGN);
+#endif
+#ifdef SIGVTALRM
+  sigaction (SIGVTALRM, &process_fatal_action, 0);
+#endif
+#ifdef SIGXCPU
+  sigaction (SIGXCPU, &process_fatal_action, 0);
+#endif
+#ifdef SIGXFSZ
+  sigaction (SIGXFSZ, &process_fatal_action, 0);
+#endif
+
+#ifdef SIGDANGER
+  /* This just means available memory is getting low.  */
+  emacs_sigaction_init (&action, deliver_danger_signal);
+  sigaction (SIGDANGER, &action, 0);
+#endif
+
+  /* AIX-specific signals.  */
+#ifdef SIGGRANT
+  sigaction (SIGGRANT, &process_fatal_action, 0);
+#endif
+#ifdef SIGMIGRATE
+  sigaction (SIGMIGRATE, &process_fatal_action, 0);
+#endif
+#ifdef SIGMSG
+  sigaction (SIGMSG, &process_fatal_action, 0);
+#endif
+#ifdef SIGRETRACT
+  sigaction (SIGRETRACT, &process_fatal_action, 0);
+#endif
+#ifdef SIGSAK
+  sigaction (SIGSAK, &process_fatal_action, 0);
+#endif
+#ifdef SIGSOUND
+  sigaction (SIGSOUND, &process_fatal_action, 0);
+#endif
+#ifdef SIGTALRM
+  sigaction (SIGTALRM, &thread_fatal_action, 0);
+#endif
 }
 \f
 #ifndef HAVE_RANDOM
@@ -1765,19 +1983,37 @@ init_signals (void)
 #endif /* !RAND_BITS */
 
 void
-seed_random (long int arg)
+seed_random (void *seed, ptrdiff_t seed_size)
 {
+#if defined HAVE_RANDOM || ! defined HAVE_LRAND48
+  unsigned int arg = 0;
+#else
+  long int arg = 0;
+#endif
+  unsigned char *argp = (unsigned char *) &arg;
+  unsigned char *seedp = seed;
+  ptrdiff_t i;
+  for (i = 0; i < seed_size; i++)
+    argp[i % sizeof arg] ^= seedp[i];
 #ifdef HAVE_RANDOM
-  srandom ((unsigned int)arg);
+  srandom (arg);
 #else
 # ifdef HAVE_LRAND48
   srand48 (arg);
 # else
-  srand ((unsigned int)arg);
+  srand (arg);
 # endif
 #endif
 }
 
+void
+init_random (void)
+{
+  EMACS_TIME t = current_emacs_time ();
+  uintmax_t v = getpid () ^ EMACS_SECS (t) ^ EMACS_NSECS (t);
+  seed_random (&v, sizeof v);
+}
+
 /*
  * Return a nonnegative random integer out of whatever we've got.
  * It contains enough bits to make a random (signed) Emacs fixnum.
@@ -1838,6 +2074,46 @@ snprintf (char *buf, size_t bufsize, char const *format, ...)
 }
 #endif
 \f
+/* If a backtrace is available, output the top lines of it to stderr.
+   Do not output more than BACKTRACE_LIMIT or BACKTRACE_LIMIT_MAX lines.
+   This function may be called from a signal handler, so it should
+   not invoke async-unsafe functions like malloc.  */
+void
+emacs_backtrace (int backtrace_limit)
+{
+  void *main_backtrace_buffer[BACKTRACE_LIMIT_MAX + 1];
+  int bounded_limit = min (backtrace_limit, BACKTRACE_LIMIT_MAX);
+  void *buffer;
+  int npointers;
+
+  if (thread_backtrace_npointers)
+    {
+      buffer = thread_backtrace_buffer;
+      npointers = thread_backtrace_npointers;
+    }
+  else
+    {
+      buffer = main_backtrace_buffer;
+      npointers = backtrace (buffer, bounded_limit + 1);
+    }
+
+  if (npointers)
+    {
+      ignore_value (write (STDERR_FILENO, "\nBacktrace:\n", 12));
+      backtrace_symbols_fd (buffer, npointers, STDERR_FILENO);
+      if (bounded_limit < npointers)
+       ignore_value (write (STDERR_FILENO, "...\n", 4));
+    }
+}
+\f
+#ifndef HAVE_NTGUI
+void
+emacs_abort (void)
+{
+  terminate_due_to_signal (SIGABRT, 10);
+}
+#endif
+
 int
 emacs_open (const char *path, int oflag, int mode)
 {
@@ -1915,11 +2191,10 @@ emacs_write (int fildes, const char *buf, ptrdiff_t nbyte)
        {
          if (errno == EINTR)
            {
-#ifdef SYNC_INPUT
              /* I originally used `QUIT' but that might causes files to
                 be truncated if you hit C-g in the middle of it.  --Stef  */
-             process_pending_signals ();
-#endif
+             if (pending_signals)
+               process_pending_signals ();
              continue;
            }
          else
@@ -1950,95 +2225,6 @@ emacs_readlink (char const *filename, char initial_buf[READLINK_BUFSIZE])
                       &emacs_norealloc_allocator, careadlinkatcwd);
 }
 \f
-#ifdef USG
-/*
- *     All of the following are for USG.
- *
- *     On USG systems the system calls are INTERRUPTIBLE by signals
- *     that the user program has elected to catch.  Thus the system call
- *     must be retried in these cases.  To handle this without massive
- *     changes in the source code, we remap the standard system call names
- *     to names for our own functions in sysdep.c that do the system call
- *     with retries.  Actually, for portability reasons, it is good
- *     programming practice, as this example shows, to limit all actual
- *     system calls to a single occurrence in the source.  Sure, this
- *     adds an extra level of function call overhead but it is almost
- *     always negligible.   Fred Fish, Unisoft Systems Inc.
- */
-
-/*
- *     Warning, this function may not duplicate 4.2 action properly
- *     under error conditions.
- */
-
-#if !defined (HAVE_GETWD) || defined (BROKEN_GETWD)
-
-#ifndef MAXPATHLEN
-/* In 4.1, param.h fails to define this.  */
-#define MAXPATHLEN 1024
-#endif
-
-char *
-getwd (char *pathname)
-{
-  char *npath, *spath;
-  extern char *getcwd (char *, size_t);
-
-  BLOCK_INPUT;                 /* getcwd uses malloc */
-  spath = npath = getcwd ((char *) 0, MAXPATHLEN);
-  if (spath == 0)
-    {
-      UNBLOCK_INPUT;
-      return spath;
-    }
-  /* On Altos 3068, getcwd can return @hostname/dir, so discard
-     up to first slash.  Should be harmless on other systems.  */
-  while (*npath && *npath != '/')
-    npath++;
-  strcpy (pathname, npath);
-  free (spath);                        /* getcwd uses malloc */
-  UNBLOCK_INPUT;
-  return pathname;
-}
-
-#endif /* !defined (HAVE_GETWD) || defined (BROKEN_GETWD) */
-
-/*
- *     This function will go away as soon as all the stubs fixed. (fnf)
- */
-
-void
-croak (char *badfunc)
-{
-  printf ("%s not yet implemented\r\n", badfunc);
-  reset_all_sys_modes ();
-  exit (1);
-}
-
-#endif /* USG */
-\f
-/* Directory routines for systems that don't have them. */
-
-#ifdef HAVE_DIRENT_H
-
-#include <dirent.h>
-
-#if !defined (HAVE_CLOSEDIR)
-
-int
-closedir (DIR *dirp /* stream from opendir */)
-{
-  int rtnval;
-
-  rtnval = emacs_close (dirp->dd_fd);
-  xfree (dirp);
-
-  return rtnval;
-}
-#endif /* not HAVE_CLOSEDIR */
-#endif /* HAVE_DIRENT_H */
-
-\f
 /* Return a struct timeval that is roughly equivalent to T.
    Use the least timeval not less than T.
    Return an extremal value if the result would overflow.  */
@@ -2078,40 +2264,27 @@ set_file_times (int fd, const char *filename,
   return fdutimens (fd, filename, timespec);
 }
 \f
-#ifndef HAVE_STRSIGNAL
-char *
-strsignal (int code)
+/* Like strsignal, except async-signal-safe, and this function typically
+   returns a string in the C locale rather than the current locale.  */
+char const *
+safe_strsignal (int code)
 {
-  char *signame = 0;
+  char const *signame = 0;
 
-  if (0 <= code && code < NSIG)
-    {
-      /* Cast to suppress warning if the table has const char *.  */
-      signame = (char *) sys_siglist[code];
-    }
+  if (0 <= code && code < sys_siglist_entries)
+    signame = sys_siglist[code];
+  if (! signame)
+    signame = "Unknown signal";
 
   return signame;
 }
-#endif /* HAVE_STRSIGNAL */
 \f
 #ifndef DOS_NT
 /* For make-serial-process  */
 int
 serial_open (char *port)
 {
-  int fd = -1;
-
-  fd = emacs_open ((char*) port,
-                  O_RDWR
-#ifdef O_NONBLOCK
-                  | O_NONBLOCK
-#else
-                  | O_NDELAY
-#endif
-#ifdef O_NOCTTY
-                  | O_NOCTTY
-#endif
-                  , 0);
+  int fd = emacs_open (port, O_RDWR | O_NOCTTY | O_NONBLOCK, 0);
   if (fd < 0)
     {
       error ("Could not open %s: %s",
@@ -2159,7 +2332,7 @@ serial_configure (struct Lisp_Process *p,
   int err = -1;
   char summary[4] = "???"; /* This usually becomes "8N1".  */
 
-  childp2 = Fcopy_sequence (PGET (p, childp));
+  childp2 = Fcopy_sequence (p->childp);
 
   /* Read port attributes and prepare default configuration.  */
   err = tcgetattr (p->outfd, &attr);
@@ -2177,7 +2350,7 @@ serial_configure (struct Lisp_Process *p,
   if (!NILP (Fplist_member (contact, QCspeed)))
     tem = Fplist_get (contact, QCspeed);
   else
-    tem = Fplist_get (PGET (p, childp), QCspeed);
+    tem = Fplist_get (p->childp, QCspeed);
   CHECK_NUMBER (tem);
   err = cfsetspeed (&attr, XINT (tem));
   if (err != 0)
@@ -2189,7 +2362,7 @@ serial_configure (struct Lisp_Process *p,
   if (!NILP (Fplist_member (contact, QCbytesize)))
     tem = Fplist_get (contact, QCbytesize);
   else
-    tem = Fplist_get (PGET (p, childp), QCbytesize);
+    tem = Fplist_get (p->childp, QCbytesize);
   if (NILP (tem))
     tem = make_number (8);
   CHECK_NUMBER (tem);
@@ -2210,7 +2383,7 @@ serial_configure (struct Lisp_Process *p,
   if (!NILP (Fplist_member (contact, QCparity)))
     tem = Fplist_get (contact, QCparity);
   else
-    tem = Fplist_get (PGET (p, childp), QCparity);
+    tem = Fplist_get (p->childp, QCparity);
   if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
     error (":parity must be nil (no parity), `even', or `odd'");
 #if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK)
@@ -2243,7 +2416,7 @@ serial_configure (struct Lisp_Process *p,
   if (!NILP (Fplist_member (contact, QCstopbits)))
     tem = Fplist_get (contact, QCstopbits);
   else
-    tem = Fplist_get (PGET (p, childp), QCstopbits);
+    tem = Fplist_get (p->childp, QCstopbits);
   if (NILP (tem))
     tem = make_number (1);
   CHECK_NUMBER (tem);
@@ -2265,7 +2438,7 @@ serial_configure (struct Lisp_Process *p,
   if (!NILP (Fplist_member (contact, QCflowcontrol)))
     tem = Fplist_get (contact, QCflowcontrol);
   else
-    tem = Fplist_get (PGET (p, childp), QCflowcontrol);
+    tem = Fplist_get (p->childp, QCflowcontrol);
   if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
     error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
 #if defined (CRTSCTS)
@@ -2307,8 +2480,7 @@ serial_configure (struct Lisp_Process *p,
     error ("tcsetattr() failed: %s", emacs_strerror (errno));
 
   childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
-  PSET (p, childp, childp2);
-
+  pset_childp (p, childp2);
 }
 #endif /* not DOS_NT  */
 \f
@@ -2445,7 +2617,7 @@ get_up_time (void)
   FILE *fup;
   EMACS_TIME up = make_emacs_time (0, 0);
 
-  BLOCK_INPUT;
+  block_input ();
   fup = fopen ("/proc/uptime", "r");
 
   if (fup)
@@ -2476,7 +2648,7 @@ get_up_time (void)
        }
       fclose (fup);
     }
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   return up;
 }
@@ -2490,7 +2662,7 @@ procfs_ttyname (int rdev)
   FILE *fdev = NULL;
   char name[PATH_MAX];
 
-  BLOCK_INPUT;
+  block_input ();
   fdev = fopen ("/proc/tty/drivers", "r");
 
   if (fdev)
@@ -2522,7 +2694,7 @@ procfs_ttyname (int rdev)
        }
       fclose (fdev);
     }
-  UNBLOCK_INPUT;
+  unblock_input ();
   return build_string (name);
 }
 
@@ -2532,7 +2704,7 @@ procfs_get_total_memory (void)
   FILE *fmem = NULL;
   unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */
 
-  BLOCK_INPUT;
+  block_input ();
   fmem = fopen ("/proc/meminfo", "r");
 
   if (fmem)
@@ -2551,7 +2723,7 @@ procfs_get_total_memory (void)
        }
       fclose (fmem);
     }
-  UNBLOCK_INPUT;
+  unblock_input ();
   return retval;
 }
 
@@ -2597,17 +2769,17 @@ system_process_attributes (Lisp_Object pid)
   /* euid egid */
   uid = st.st_uid;
   attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
-  BLOCK_INPUT;
+  block_input ();
   pw = getpwuid (uid);
-  UNBLOCK_INPUT;
+  unblock_input ();
   if (pw)
     attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
 
   gid = st.st_gid;
   attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs);
-  BLOCK_INPUT;
+  block_input ();
   gr = getgrgid (gid);
-  UNBLOCK_INPUT;
+  unblock_input ();
   if (gr)
     attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
 
@@ -2733,7 +2905,7 @@ system_process_attributes (Lisp_Object pid)
          if (emacs_read (fd, &ch, 1) != 1)
            break;
          c = ch;
-         if (isspace (c) || c == '\\')
+         if (c_isspace (c) || c == '\\')
            cmdline_size++;     /* for later quoting, see below */
        }
       if (cmdline_size)
@@ -2757,7 +2929,7 @@ system_process_attributes (Lisp_Object pid)
          for (p = cmdline; p < cmdline + nread; p++)
            {
              /* Escape-quote whitespace and backslashes.  */
-             if (isspace (*p) || *p == '\\')
+             if (c_isspace (*p) || *p == '\\')
                {
                  memmove (p + 1, p, nread - (p - cmdline));
                  nread++;
@@ -2835,17 +3007,17 @@ system_process_attributes (Lisp_Object pid)
   /* euid egid */
   uid = st.st_uid;
   attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
-  BLOCK_INPUT;
+  block_input ();
   pw = getpwuid (uid);
-  UNBLOCK_INPUT;
+  unblock_input ();
   if (pw)
     attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
 
   gid = st.st_gid;
   attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs);
-  BLOCK_INPUT;
+  block_input ();
   gr = getgrgid (gid);
-  UNBLOCK_INPUT;
+  unblock_input ();
   if (gr)
     attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
 
@@ -2966,17 +3138,17 @@ system_process_attributes (Lisp_Object pid)
 
   attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (proc.ki_uid)), attrs);
 
-  BLOCK_INPUT;
+  block_input ();
   pw = getpwuid (proc.ki_uid);
-  UNBLOCK_INPUT;
+  unblock_input ();
   if (pw)
     attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
 
   attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (proc.ki_svgid)), attrs);
 
-  BLOCK_INPUT;
+  block_input ();
   gr = getgrgid (proc.ki_svgid);
-  UNBLOCK_INPUT;
+  unblock_input ();
   if (gr)
     attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
 
@@ -3016,9 +3188,9 @@ system_process_attributes (Lisp_Object pid)
   attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (proc.ki_pgid)), attrs);
   attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (proc.ki_sid)),  attrs);
 
-  BLOCK_INPUT;
+  block_input ();
   ttyname = proc.ki_tdev == NODEV ? NULL : devname (proc.ki_tdev, S_IFCHR);
-  UNBLOCK_INPUT;
+  unblock_input ();
   if (ttyname)
     attrs = Fcons (Fcons (Qtty, build_string (ttyname)), attrs);