]> code.delx.au - gnu-emacs/blobdiff - src/process.c
(xic_create_xfontset): Fix previous change.
[gnu-emacs] / src / process.c
index 1c0b196b3cf5c3d7b3faeb5219d384d5b819d292..ebe8ef56fff55a2678a7fa8be42c380d632481b2 100644 (file)
@@ -318,6 +318,12 @@ static int read_process_output P_ ((Lisp_Object, int));
 #define POLL_FOR_INPUT
 #endif
 
+static Lisp_Object get_process ();
+static void exec_sentinel ();
+
+extern EMACS_TIME timer_check ();
+extern int timers_run;
+\f
 /* Mask of bits indicating the descriptors that we wait for input on.  */
 
 static SELECT_TYPE input_wait_mask;
@@ -386,15 +392,13 @@ struct sockaddr_and_len {
 #define DATAGRAM_CONN_P(proc)  (0)
 #endif
 
-static Lisp_Object get_process ();
-static void exec_sentinel ();
-
-extern EMACS_TIME timer_check ();
-extern int timers_run;
-
 /* Maximum number of bytes to send to a pty without an eof.  */
 static int pty_max_bytes;
 
+/* Nonzero means don't run process sentinels.  This is used
+   when exiting.  */
+int inhibit_sentinels;
+
 #ifdef HAVE_PTYS
 #ifdef HAVE_PTY_H
 #include <pty.h>
@@ -414,10 +418,10 @@ update_status (p)
      struct Lisp_Process *p;
 {
   union { int i; WAITTYPE wt; } u;
-  u.i = XFASTINT (p->raw_status_low) + (XFASTINT (p->raw_status_high) << 16);
+  eassert (p->raw_status_new);
+  u.i = p->raw_status;
   p->status = status_convert (u.wt);
-  p->raw_status_low = Qnil;
-  p->raw_status_high = Qnil;
+  p->raw_status_new = 0;
 }
 
 /*  Convert a process status word in Unix format to
@@ -619,11 +623,10 @@ make_process (name)
 
   XSETINT (p->infd, -1);
   XSETINT (p->outfd, -1);
-  XSETFASTINT (p->pid, 0);
   XSETFASTINT (p->tick, 0);
   XSETFASTINT (p->update_tick, 0);
-  p->raw_status_low = Qnil;
-  p->raw_status_high = Qnil;
+  p->pid = 0;
+  p->raw_status_new = 0;
   p->status = Qrun;
   p->mark = Fmake_marker ();
 
@@ -696,6 +699,8 @@ setup_process_coding_systems (process)
       = (struct coding_system *) xmalloc (sizeof (struct coding_system));
   setup_coding_system (p->encode_coding_system,
                       proc_encode_coding_system[outch]);
+  if (proc_encode_coding_system[outch]->eol_type == CODING_EOL_UNDECIDED)
+    proc_encode_coding_system[outch]->eol_type = system_eol_type;
 }
 \f
 DEFUN ("processp", Fprocessp, Sprocessp, 1, 1, 0,
@@ -777,6 +782,16 @@ get_process (name)
   return proc;
 }
 
+
+#ifdef SIGCHLD
+/* Fdelete_process promises to immediately forget about the process, but in
+   reality, Emacs needs to remember those processes until they have been
+   treated by sigchld_handler; otherwise this handler would consider the
+   process as being synchronous and say that the synchronous process is
+   dead.  */
+static Lisp_Object deleted_pid_list;
+#endif
+
 DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0,
        doc: /* Delete PROCESS: kill it and forget about it immediately.
 PROCESS may be a process, a buffer, the name of a process or buffer, or
@@ -789,8 +804,7 @@ nil, indicating the current buffer's process.  */)
   process = get_process (process);
   p = XPROCESS (process);
 
-  p->raw_status_low = Qnil;
-  p->raw_status_high = Qnil;
+  p->raw_status_new = 0;
   if (NETCONN1_P (p))
     {
       p->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
@@ -799,12 +813,31 @@ nil, indicating the current buffer's process.  */)
     }
   else if (XINT (p->infd) >= 0)
     {
-      Fkill_process (process, Qnil);
-      /* Do this now, since remove_process will make sigchld_handler do nothing.  */
-      p->status
-       = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
-      XSETINT (p->tick, ++process_tick);
-      status_notify (p);
+#ifdef SIGCHLD
+      Lisp_Object symbol;
+
+      /* No problem storing the pid here, as it is still in Vprocess_alist.  */
+      deleted_pid_list = Fcons (make_fixnum_or_float (p->pid),
+                               /* GC treated elements set to nil.  */
+                               Fdelq (Qnil, deleted_pid_list));
+      /* If the process has already signaled, remove it from the list.  */
+      if (p->raw_status_new)
+       update_status (p);
+      symbol = p->status;
+      if (CONSP (p->status))
+       symbol = XCAR (p->status);
+      if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
+       Fdelete (make_fixnum_or_float (p->pid), deleted_pid_list);
+      else
+#endif
+       {
+         Fkill_process (process, Qnil);
+         /* Do this now, since remove_process will make sigchld_handler do nothing.  */
+         p->status
+           = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
+         XSETINT (p->tick, ++process_tick);
+         status_notify (p);
+       }
     }
   remove_process (process);
   return Qnil;
@@ -840,7 +873,7 @@ nil, indicating the current buffer's process.  */)
     return process;
 
   p = XPROCESS (process);
-  if (!NILP (p->raw_status_low))
+  if (p->raw_status_new)
     update_status (p);
   status = p->status;
   if (CONSP (status))
@@ -865,7 +898,7 @@ If PROCESS has not yet exited or died, return 0.  */)
      register Lisp_Object process;
 {
   CHECK_PROCESS (process);
-  if (!NILP (XPROCESS (process)->raw_status_low))
+  if (XPROCESS (process)->raw_status_new)
     update_status (XPROCESS (process));
   if (CONSP (XPROCESS (process)->status))
     return XCAR (XCDR (XPROCESS (process)->status));
@@ -880,7 +913,9 @@ For a network connection, this value is nil.  */)
      register Lisp_Object process;
 {
   CHECK_PROCESS (process);
-  return XPROCESS (process)->pid;
+  return (XPROCESS (process)->pid
+         ? make_fixnum_or_float (XPROCESS (process)->pid)
+         : Qnil);
 }
 
 DEFUN ("process-name", Fprocess_name, Sprocess_name, 1, 1, 0,
@@ -1279,6 +1314,7 @@ list_processes_1 (query_only)
   register struct Lisp_Process *p;
   char tembuf[300];
   int w_proc, w_buffer, w_tty;
+  int exited = 0;
   Lisp_Object i_status, i_buffer, i_tty, i_command;
 
   w_proc = 4;    /* Proc   */
@@ -1362,7 +1398,7 @@ list_processes_1 (query_only)
       Finsert (1, &p->name);
       Findent_to (i_status, minspace);
 
-      if (!NILP (p->raw_status_low))
+      if (p->raw_status_new)
        update_status (p);
       symbol = p->status;
       if (CONSP (p->status))
@@ -1405,8 +1441,8 @@ list_processes_1 (query_only)
            }
        }
 
-      if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
-       remove_process (proc);
+      if (EQ (symbol, Qsignal) || EQ (symbol, Qexit) || EQ (symbol, Qclosed))
+       exited++;
 
       Findent_to (i_buffer, minspace);
       if (NILP (p->buffer))
@@ -1470,6 +1506,8 @@ list_processes_1 (query_only)
          insert_string ("\n");
        }
     }
+  if (exited)
+    status_notify (NULL);
   return Qnil;
 }
 
@@ -1734,7 +1772,7 @@ start_process_unwind (proc)
     abort ();
 
   /* Was PROC started successfully?  */
-  if (XINT (XPROCESS (proc)->pid) <= 0)
+  if (XPROCESS (proc)->pid <= 0)
     remove_process (proc);
 
   return Qnil;
@@ -1945,7 +1983,7 @@ create_process (process, new_argv, current_dir)
      in the table after this function has returned; if it does
      it might cause call-process to hang and subsequent asynchronous
      processes to get their return values scrambled.  */
-  XSETINT (XPROCESS (process)->pid, -1);
+  XPROCESS (process)->pid = -1;
 
   BLOCK_INPUT;
 
@@ -2136,7 +2174,7 @@ create_process (process, new_argv, current_dir)
   else
     {
       /* vfork succeeded.  */
-      XSETFASTINT (XPROCESS (process)->pid, pid);
+      XPROCESS (process)->pid = pid;
 
 #ifdef WINDOWSNT
       register_child (pid, inchannel);
@@ -2322,7 +2360,11 @@ get_lisp_to_sockaddr_size (address, familyp)
 }
 
 /* Convert an address object (vector or string) to an internal sockaddr.
-   Format of address has already been validated by size_lisp_to_sockaddr.  */
+
+   The address format has been basically validated by
+   get_lisp_to_sockaddr_size, but this does not mean FAMILY is valid;
+   it could have come from user data.  So if FAMILY is not valid,
+   we return after zeroing *SA.  */
 
 static void
 conv_lisp_to_sockaddr (family, address, sa, len)
@@ -2336,7 +2378,6 @@ conv_lisp_to_sockaddr (family, address, sa, len)
   register int i;
 
   bzero (sa, len);
-  sa->sa_family = family;
 
   if (VECTORP (address))
     {
@@ -2348,6 +2389,7 @@ conv_lisp_to_sockaddr (family, address, sa, len)
          i = XINT (p->contents[--len]);
          sin->sin_port = htons (i);
          cp = (unsigned char *)&sin->sin_addr;
+         sa->sa_family = family;
        }
 #ifdef AF_INET6
       else if (family == AF_INET6)
@@ -2363,9 +2405,10 @@ conv_lisp_to_sockaddr (family, address, sa, len)
                int j = XFASTINT (p->contents[i]) & 0xffff;
                ip6[i] = ntohs (j);
              }
-         return;
+         sa->sa_family = family;
        }
 #endif
+      return;
     }
   else if (STRINGP (address))
     {
@@ -2376,6 +2419,7 @@ conv_lisp_to_sockaddr (family, address, sa, len)
          cp = SDATA (address);
          for (i = 0; i < sizeof (sockun->sun_path) && *cp; i++)
            sockun->sun_path[i] = *cp++;
+         sa->sa_family = family;
        }
 #endif
       return;
@@ -3349,7 +3393,7 @@ usage: (make-network-process &rest ARGS)  */)
     p->kill_without_query = Qt;
   if ((tem = Fplist_get (contact, QCstop), !NILP (tem)))
     p->command = Qt;
-  p->pid = Qnil;
+  p->pid = 0;
   XSETINT (p->infd, inch);
   XSETINT (p->outfd, outch);
   if (is_server && socktype == SOCK_STREAM)
@@ -3838,62 +3882,60 @@ DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output,
 It is read into the process' buffers or given to their filter functions.
 Non-nil arg PROCESS means do not return until some output has been received
 from PROCESS.
-Non-nil second arg TIMEOUT and third arg TIMEOUT-MSECS are number of
-seconds and microseconds to wait; return after that much time whether
-or not there is input.
+
+Non-nil second arg SECONDS and third arg MILLISEC are number of
+seconds and milliseconds to wait; return after that much time whether
+or not there is input.  If SECONDS is a floating point number,
+it specifies a fractional number of seconds to wait.
+
 If optional fourth arg JUST-THIS-ONE is non-nil, only accept output
 from PROCESS, suspending reading output from other processes.
 If JUST-THIS-ONE is an integer, don't run any timers either.
 Return non-nil iff we received any output before the timeout expired.  */)
-     (process, timeout, timeout_msecs, just_this_one)
-     register Lisp_Object process, timeout, timeout_msecs, just_this_one;
+     (process, seconds, millisec, just_this_one)
+     register Lisp_Object process, seconds, millisec, just_this_one;
 {
-  int seconds;
-  int useconds;
+  int secs, usecs = 0;
 
   if (! NILP (process))
     CHECK_PROCESS (process);
   else
     just_this_one = Qnil;
 
-  if (! NILP (timeout_msecs))
+  if (!NILP (seconds))
     {
-      CHECK_NUMBER (timeout_msecs);
-      useconds = XINT (timeout_msecs);
-      if (!INTEGERP (timeout))
-       XSETINT (timeout, 0);
-
-      {
-       int carry = useconds / 1000000;
-
-       XSETINT (timeout, XINT (timeout) + carry);
-       useconds -= carry * 1000000;
+      if (INTEGERP (seconds))
+       secs = XINT (seconds);
+      else if (FLOATP (seconds))
+       {
+         double timeout = XFLOAT_DATA (seconds);
+         secs = (int) timeout;
+         usecs = (int) ((timeout - (double) secs) * 1000000);
+       }
+      else
+       wrong_type_argument (Qnumberp, seconds);
 
-       /* I think this clause is necessary because C doesn't
-          guarantee a particular rounding direction for negative
-          integers.  */
-       if (useconds < 0)
-         {
-           XSETINT (timeout, XINT (timeout) - 1);
-           useconds += 1000000;
-         }
-      }
-    }
-  else
-    useconds = 0;
+      if (INTEGERP (millisec))
+       {
+         int carry;
+         usecs += XINT (millisec) * 1000;
+         carry = usecs / 1000000;
+         secs += carry;
+         if ((usecs -= carry * 1000000) < 0)
+           {
+             secs--;
+             usecs += 1000000;
+           }
+       }
 
-  if (! NILP (timeout))
-    {
-      CHECK_NUMBER (timeout);
-      seconds = XINT (timeout);
-      if (seconds < 0 || (seconds == 0 && useconds == 0))
-       seconds = -1;
+      if (secs < 0 || (secs == 0 && usecs == 0))
+       secs = -1, usecs = 0;
     }
   else
-    seconds = NILP (process) ? -1 : 0;
+    secs = NILP (process) ? -1 : 0;
 
   return
-    (wait_reading_process_output (seconds, useconds, 0, 0,
+    (wait_reading_process_output (secs, usecs, 0, 0,
                                  Qnil,
                                  !NILP (process) ? XPROCESS (process) : NULL,
                                  NILP (just_this_one) ? 0 :
@@ -4067,7 +4109,7 @@ server_accept_connection (server, channel)
   p->sentinel = ps->sentinel;
   p->filter = ps->filter;
   p->command = Qnil;
-  p->pid = Qnil;
+  p->pid = 0;
   XSETINT (p->infd, s);
   XSETINT (p->outfd, s);
   p->status = Qrun;
@@ -4123,12 +4165,39 @@ server_accept_connection (server, channel)
    when not inside wait_reading_process_output.  */
 static int waiting_for_user_input_p;
 
+static Lisp_Object
+wait_reading_process_output_unwind (data)
+     Lisp_Object data;
+{
+  waiting_for_user_input_p = XINT (data);
+  return Qnil;
+}
+
 /* This is here so breakpoints can be put on it.  */
 static void
 wait_reading_process_output_1 ()
 {
 }
 
+/* Use a wrapper around select to work around a bug in gdb 5.3.
+   Normally, the wrapper is optimzed away by inlining.
+
+   If emacs is stopped inside select, the gdb backtrace doesn't
+   show the function which called select, so it is practically
+   impossible to step through wait_reading_process_output.  */
+
+#ifndef select
+static INLINE int
+select_wrapper (n, rfd, wfd, xfd, tmo)
+  int n;
+  SELECT_TYPE *rfd, *wfd, *xfd;
+  EMACS_TIME *tmo;
+{
+  return select (n, rfd, wfd, xfd, tmo);
+}
+#define select select_wrapper
+#endif
+
 /* Read and dispose of subprocess output while waiting for timeout to
    elapse and/or keyboard input to be available.
 
@@ -4186,9 +4255,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
   EMACS_TIME timeout, end_time;
   int wait_channel = -1;
   int got_some_input = 0;
-  /* Either nil or a cons cell, the car of which is of interest and
-     may be changed outside of this routine.  */
-  int saved_waiting_for_user_input_p = waiting_for_user_input_p;
+  int count = SPECPDL_INDEX ();
 
   FD_ZERO (&Available);
 #ifdef NON_BLOCKING_CONNECT
@@ -4199,6 +4266,8 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
   if (wait_proc != NULL)
     wait_channel = XINT (wait_proc->infd);
 
+  record_unwind_protect (wait_reading_process_output_unwind,
+                        make_number (waiting_for_user_input_p));
   waiting_for_user_input_p = read_kbd;
 
   /* Since we may need to wait several times,
@@ -4367,9 +4436,9 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
 
       /* Don't wait for output from a non-running process.  Just
          read whatever data has already been received.  */
-      if (wait_proc != 0 && !NILP (wait_proc->raw_status_low))
+      if (wait_proc && wait_proc->raw_status_new)
        update_status (wait_proc);
-      if (wait_proc != 0
+      if (wait_proc
          && ! EQ (wait_proc->status, Qrun)
          && ! EQ (wait_proc->status, Qconnect))
        {
@@ -4753,7 +4822,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
                  /* Preserve status of processes already terminated.  */
                  XSETINT (XPROCESS (proc)->tick, ++process_tick);
                  deactivate_process (proc);
-                 if (!NILP (XPROCESS (proc)->raw_status_low))
+                 if (XPROCESS (proc)->raw_status_new)
                    update_status (XPROCESS (proc));
                  if (EQ (XPROCESS (proc)->status, Qrun))
                    XPROCESS (proc)->status
@@ -4825,7 +4894,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
        }                       /* end for each file descriptor */
     }                          /* end while exit conditions not met */
 
-  waiting_for_user_input_p = saved_waiting_for_user_input_p;
+  unbind_to (count, Qnil);
 
   /* If calling from keyboard input, do not quit
      since we want to return C-g as an input character.
@@ -5062,6 +5131,10 @@ read_process_output (proc, channel)
              p->encode_coding_system = coding->symbol;
              setup_coding_system (coding->symbol,
                                   proc_encode_coding_system[XINT (p->outfd)]);
+             if (proc_encode_coding_system[XINT (p->outfd)]->eol_type
+                 == CODING_EOL_UNDECIDED)
+               proc_encode_coding_system[XINT (p->outfd)]->eol_type
+                 = system_eol_type;
            }
        }
 
@@ -5102,7 +5175,7 @@ read_process_output (proc, channel)
 #endif
        /* But do it only if the caller is actually going to read events.
           Otherwise there's no need to make him wake up, and it could
-          cause trouble (for example it would make Fsit_for return).  */
+          cause trouble (for example it would make sit_for return).  */
        if (waiting_for_user_input_p == -1)
          record_asynch_buffer_change ();
 
@@ -5169,6 +5242,10 @@ read_process_output (proc, channel)
              p->encode_coding_system = coding->symbol;
              setup_coding_system (coding->symbol,
                                   proc_encode_coding_system[XINT (p->outfd)]);
+             if (proc_encode_coding_system[XINT (p->outfd)]->eol_type
+                 == CODING_EOL_UNDECIDED)
+               proc_encode_coding_system[XINT (p->outfd)]->eol_type
+                 = system_eol_type;
            }
        }
       carryover = nbytes - coding->consumed;
@@ -5290,7 +5367,7 @@ send_process (proc, buf, len, object)
   VMS_PROC_STUFF *vs, *get_vms_process_pointer();
 #endif /* VMS */
 
-  if (! NILP (p->raw_status_low))
+  if (p->raw_status_new)
     update_status (p);
   if (! EQ (p->status, Qrun))
     error ("Process %s not running", SDATA (p->name));
@@ -5311,6 +5388,8 @@ send_process (proc, buf, len, object)
           sending a multibyte text, thus we must encode it by the
           original coding system specified for the current process.  */
        setup_coding_system (p->encode_coding_system, coding);
+      if (coding->eol_type == CODING_EOL_UNDECIDED)
+       coding->eol_type = system_eol_type;
       /* src_multibyte should be set to 1 _after_ a call to
         setup_coding_system, since it resets src_multibyte to
         zero.  */
@@ -5554,8 +5633,7 @@ send_process (proc, buf, len, object)
       proc = process_sent_to;
       p = XPROCESS (proc);
 #endif
-      p->raw_status_low = Qnil;
-      p->raw_status_high = Qnil;
+      p->raw_status_new = 0;
       p->status = Fcons (Qexit, Fcons (make_number (256), Qnil));
       XSETINT (p->tick, ++process_tick);
       deactivate_process (proc);
@@ -5670,7 +5748,7 @@ return t unconditionally.  */)
 
   gid = emacs_get_tty_pgrp (p);
 
-  if (gid == XFASTINT (p->pid))
+  if (gid == p->pid)
     return Qnil;
   return Qt;
 }
@@ -5717,7 +5795,7 @@ process_send_signal (process, signo, current_group, nomsg)
   /* If we are using pgrps, get a pgrp number and make it negative.  */
   if (NILP (current_group))
     /* Send the signal to the shell's process group.  */
-    gid = XFASTINT (p->pid);
+    gid = p->pid;
   else
     {
 #ifdef SIGNALS_VIA_CHARACTERS
@@ -5836,7 +5914,7 @@ process_send_signal (process, signo, current_group, nomsg)
       if (gid == -1)
        /* If we can't get the information, assume
           the shell owns the tty.  */
-       gid = XFASTINT (p->pid);
+       gid = p->pid;
 
       /* It is not clear whether anything really can set GID to -1.
         Perhaps on some system one of those ioctls can or could do so.
@@ -5846,12 +5924,12 @@ process_send_signal (process, signo, current_group, nomsg)
 #else  /* ! defined (TIOCGPGRP ) */
       /* Can't select pgrps on this system, so we know that
         the child itself heads the pgrp.  */
-      gid = XFASTINT (p->pid);
+      gid = p->pid;
 #endif /* ! defined (TIOCGPGRP ) */
 
       /* If current_group is lambda, and the shell owns the terminal,
         don't send any signal.  */
-      if (EQ (current_group, Qlambda) && gid == XFASTINT (p->pid))
+      if (EQ (current_group, Qlambda) && gid == p->pid)
        return;
     }
 
@@ -5859,8 +5937,7 @@ process_send_signal (process, signo, current_group, nomsg)
     {
 #ifdef SIGCONT
     case SIGCONT:
-      p->raw_status_low = Qnil;
-      p->raw_status_high = Qnil;
+      p->raw_status_new = 0;
       p->status = Qrun;
       XSETINT (p->tick, ++process_tick);
       if (!nomsg)
@@ -5879,7 +5956,7 @@ process_send_signal (process, signo, current_group, nomsg)
 #endif
     case SIGKILL:
 #ifdef VMS
-      sys$forcex (&(XFASTINT (p->pid)), 0, 1);
+      sys$forcex (&(p->pid), 0, 1);
       whoosh:
 #endif
       flush_pending_output (XINT (p->infd));
@@ -5891,7 +5968,7 @@ process_send_signal (process, signo, current_group, nomsg)
      obvious alternative.  */
   if (no_pgrp)
     {
-      kill (XFASTINT (p->pid), signo);
+      kill (p->pid, signo);
       return;
     }
 
@@ -5904,7 +5981,7 @@ process_send_signal (process, signo, current_group, nomsg)
     }
   else
     {
-      gid = - XFASTINT (p->pid);
+      gid = - p->pid;
       kill (gid, signo);
     }
 #else /* ! defined (TIOCSIGSEND) */
@@ -6024,11 +6101,17 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
      (process, sigcode)
      Lisp_Object process, sigcode;
 {
-  Lisp_Object pid;
+  pid_t pid;
 
   if (INTEGERP (process))
     {
-      pid = process;
+      pid = XINT (process);
+      goto got_it;
+    }
+
+  if (FLOATP (process))
+    {
+      pid = (pid_t) XFLOAT (process);
       goto got_it;
     }
 
@@ -6037,8 +6120,8 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
       Lisp_Object tem;
       if (tem = Fget_process (process), NILP (tem))
        {
-         pid = Fstring_to_number (process, make_number (10));
-         if (XINT (pid) != 0)
+         pid = XINT (Fstring_to_number (process, make_number (10)));
+         if (pid > 0)
            goto got_it;
        }
       process = tem;
@@ -6051,7 +6134,7 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
 
   CHECK_PROCESS (process);
   pid = XPROCESS (process)->pid;
-  if (!INTEGERP (pid) || XINT (pid) <= 0)
+  if (pid <= 0)
     error ("Cannot signal process %s", SDATA (XPROCESS (process)->name));
 
  got_it:
@@ -6170,7 +6253,7 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
 
 #undef handle_signal
 
-  return make_number (kill (XINT (pid), XINT (sigcode)));
+  return make_number (kill (pid, XINT (sigcode)));
 }
 
 DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0,
@@ -6194,7 +6277,7 @@ text to PROCESS after you call this function.  */)
   coding = proc_encode_coding_system[XINT (XPROCESS (proc)->outfd)];
 
   /* Make sure the process is really alive.  */
-  if (! NILP (XPROCESS (proc)->raw_status_low))
+  if (XPROCESS (proc)->raw_status_new)
     update_status (XPROCESS (proc));
   if (! EQ (XPROCESS (proc)->status, Qrun))
     error ("Process %s not running", SDATA (XPROCESS (proc)->name));
@@ -6219,7 +6302,7 @@ text to PROCESS after you call this function.  */)
         for communication with the subprocess, call shutdown to cause EOF.
         (In some old system, shutdown to socketpair doesn't work.
         Then we just can't win.)  */
-      if (NILP (XPROCESS (proc)->pid)
+      if (XPROCESS (proc)->pid == 0
          || XINT (XPROCESS (proc)->outfd) == XINT (XPROCESS (proc)->infd))
        shutdown (XINT (XPROCESS (proc)->outfd), 1);
       /* In case of socketpair, outfd == infd, so don't close it.  */
@@ -6229,6 +6312,8 @@ text to PROCESS after you call this function.  */)
       emacs_close (XINT (XPROCESS (proc)->outfd));
 #endif /* not HAVE_SHUTDOWN */
       new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0);
+      if (new_outfd < 0)
+       abort ();
       old_outfd = XINT (XPROCESS (proc)->outfd);
 
       if (!proc_encode_coding_system[new_outfd])
@@ -6294,6 +6379,7 @@ kill_buffer_processes (buffer)
    ** Malloc WARNING: This should never call malloc either directly or
    indirectly; if it does, that is a bug  */
 
+#ifdef SIGCHLD
 SIGTYPE
 sigchld_handler (signo)
      int signo;
@@ -6351,12 +6437,21 @@ sigchld_handler (signo)
 
       /* Find the process that signaled us, and record its status.  */
 
+      /* The process can have been deleted by Fdelete_process.  */
+      tail = Fmember (make_fixnum_or_float (pid), deleted_pid_list);
+      if (!NILP (tail))
+       {
+         Fsetcar (tail, Qnil);
+         goto sigchld_end_of_loop;
+       }
+
+      /* Otherwise, if it is asynchronous, it is in Vprocess_alist.  */
       p = 0;
       for (tail = Vprocess_alist; GC_CONSP (tail); tail = XCDR (tail))
        {
          proc = XCDR (XCAR (tail));
          p = XPROCESS (proc);
-         if (GC_EQ (p->childp, Qt) && XINT (p->pid) == pid)
+         if (GC_EQ (p->childp, Qt) && p->pid == pid)
            break;
          p = 0;
        }
@@ -6368,7 +6463,7 @@ sigchld_handler (signo)
          {
            proc = XCDR (XCAR (tail));
            p = XPROCESS (proc);
-           if (GC_INTEGERP (p->pid) && XINT (p->pid) == -1)
+           if (p->pid == -1)
              break;
            p = 0;
          }
@@ -6381,8 +6476,8 @@ sigchld_handler (signo)
 
          XSETINT (p->tick, ++process_tick);
          u.wt = w;
-         XSETINT (p->raw_status_low, u.i & 0xffff);
-         XSETINT (p->raw_status_high, u.i >> 16);
+         p->raw_status = u.i;
+         p->raw_status_new = 1;
 
          /* If process has terminated, stop waiting for its output.  */
          if ((WIFSIGNALED (w) || WIFEXITED (w))
@@ -6402,8 +6497,8 @@ sigchld_handler (signo)
            EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
        }
 
-       /* There was no asynchronous process found for that id.  Check
-          if we have a synchronous process.  */
+      /* There was no asynchronous process found for that pid: we have
+        a synchronous process.  */
       else
        {
          synch_process_alive = 0;
@@ -6420,6 +6515,9 @@ sigchld_handler (signo)
            EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
        }
 
+    sigchld_end_of_loop:
+      ;
+
       /* On some systems, we must return right away.
         If any more processes want to signal us, we will
         get another signal.
@@ -6436,6 +6534,7 @@ sigchld_handler (signo)
 #endif /* USG, but not HPUX with WNOHANG */
     }
 }
+#endif /* SIGCHLD */
 \f
 
 static Lisp_Object
@@ -6467,6 +6566,9 @@ exec_sentinel (proc, reason)
   int outer_running_asynch_code = running_asynch_code;
   int waiting = waiting_for_user_input_p;
 
+  if (inhibit_sentinels)
+    return;
+
   /* No need to gcpro these, because all we do with them later
      is test them for EQness, and none of them should be a string.  */
   odeactivate = Vdeactivate_mark;
@@ -6523,7 +6625,7 @@ exec_sentinel (proc, reason)
 #endif
     /* But do it only if the caller is actually going to read events.
        Otherwise there's no need to make him wake up, and it could
-       cause trouble (for example it would make Fsit_for return).  */
+       cause trouble (for example it would make sit_for return).  */
     if (waiting_for_user_input_p == -1)
       record_asynch_buffer_change ();
 
@@ -6579,7 +6681,7 @@ status_notify (deleting_process)
          buffer = p->buffer;
 
          /* Get the text to use for the message.  */
-         if (!NILP (p->raw_status_low))
+         if (p->raw_status_new)
            update_status (p);
          msg = status_message (p);
 
@@ -6796,6 +6898,8 @@ init_process ()
 {
   register int i;
 
+  inhibit_sentinels = 0;
+
 #ifdef SIGCHLD
 #ifndef CANNOT_DUMP
   if (! noninteractive || initialized)
@@ -6821,6 +6925,9 @@ init_process ()
   FD_SET (0, &input_wait_mask);
 
   Vprocess_alist = Qnil;
+#ifdef SIGCHLD
+  deleted_pid_list = Qnil;
+#endif
   for (i = 0; i < MAXDESC; i++)
     {
       chan_process[i] = Qnil;
@@ -6959,6 +7066,9 @@ syms_of_process ()
   staticpro (&Qlast_nonmenu_event);
 
   staticpro (&Vprocess_alist);
+#ifdef SIGCHLD
+  staticpro (&deleted_pid_list);
+#endif
 
   DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
               doc: /* *Non-nil means delete processes immediately when they exit.
@@ -6981,7 +7091,7 @@ On some systems, when Emacs reads the output from a subprocess, the output data
 is read in very small blocks, potentially resulting in very poor performance.
 This behavior can be remedied to some extent by setting this variable to a
 non-nil value, as it will automatically delay reading from such processes, to
-allowing them to produce more output before Emacs tries to read it.
+allow them to produce more output before Emacs tries to read it.
 If the value is t, the delay is reset after each write to the process; any other
 non-nil value means that the delay is not reset on write.
 The variable takes effect when `start-process' is called.  */);