]> code.delx.au - gnu-emacs/blobdiff - src/process.c
(Defining Images): Clean up previous change.
[gnu-emacs] / src / process.c
index b63c730b48082c9e8631b47356df03e0d7e2d235..18a446e956194581a101bf40446818bc6fc4f5b8 100644 (file)
@@ -1,6 +1,7 @@
 /* Asynchronous subprocess control for GNU Emacs.
-   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 96, 98, 1999,
-      2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
+                 1996, 1998, 1999, 2001, 2002, 2003, 2004,
+                 2005 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -16,8 +17,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 
 #include <config.h>
@@ -187,6 +188,7 @@ extern Lisp_Object QCfilter;
 #include "syswait.h"
 
 extern void set_waiting_for_input P_ ((EMACS_TIME *));
+extern char *get_operating_system_release ();
 
 #ifndef USE_CRT_DLL
 extern int errno;
@@ -271,17 +273,19 @@ int update_tick;
 #define READ_OUTPUT_DELAY_MAX       (READ_OUTPUT_DELAY_INCREMENT * 5)
 #define READ_OUTPUT_DELAY_MAX_MAX   (READ_OUTPUT_DELAY_INCREMENT * 7)
 
-/* Number of processes which might be delayed.  */
+/* Number of processes which have a non-zero read_output_delay,
+   and therefore might be delayed for adaptive read buffering.  */
 
 static int process_output_delay_count;
 
-/* Non-zero if any process has non-nil process_output_skip.  */
+/* Non-zero if any process has non-nil read_output_skip.  */
 
 static int process_output_skip;
 
 /* Non-nil means to delay reading process output to improve buffering.
    A value of t means that delay is reset after each send, any other
-   non-nil value does not reset the delay.  */
+   non-nil value does not reset the delay.  A value of nil disables
+   adaptive read buffering completely.  */
 static Lisp_Object Vprocess_adaptive_read_buffering;
 #else
 #define process_output_delay_count 0
@@ -290,7 +294,10 @@ static Lisp_Object Vprocess_adaptive_read_buffering;
 
 #include "sysselect.h"
 
-extern int keyboard_bit_set P_ ((SELECT_TYPE *));
+static int keyboard_bit_set P_ ((SELECT_TYPE *));
+static void deactivate_process P_ ((Lisp_Object));
+static void status_notify P_ ((struct Lisp_Process *));
+static int read_process_output P_ ((Lisp_Object, int));
 
 /* 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.  */
@@ -310,6 +317,7 @@ static SELECT_TYPE non_keyboard_wait_mask;
 
 static SELECT_TYPE non_process_wait_mask;
 
+#ifdef NON_BLOCKING_CONNECT
 /* Mask of bits indicating the descriptors that we wait for connect to
    complete on.  Once they complete, they are removed from this mask
    and added to the input_wait_mask and non_keyboard_wait_mask.  */
@@ -319,6 +327,11 @@ static SELECT_TYPE connect_wait_mask;
 /* Number of bits set in connect_wait_mask.  */
 static int num_pending_connects;
 
+#define IF_NON_BLOCKING_CONNECT(s) s
+#else
+#define IF_NON_BLOCKING_CONNECT(s)
+#endif
+
 /* The largest descriptor currently in use for a process object.  */
 static int max_process_desc;
 
@@ -369,8 +382,6 @@ extern int timers_run;
 /* Maximum number of bytes to send to a pty without an eof.  */
 static int pty_max_bytes;
 
-extern Lisp_Object Vfile_name_coding_system, Vdefault_file_name_coding_system;
-
 #ifdef HAVE_PTYS
 #ifdef HAVE_PTY_H
 #include <pty.h>
@@ -383,9 +394,9 @@ static char pty_name[24];
 /* Compute the Lisp form of the process status, p->status, from
    the numeric status that was returned by `wait'.  */
 
-Lisp_Object status_convert ();
+static Lisp_Object status_convert ();
 
-void
+static void
 update_status (p)
      struct Lisp_Process *p;
 {
@@ -399,7 +410,7 @@ update_status (p)
 /*  Convert a process status word in Unix format to
     the list that we use internally.  */
 
-Lisp_Object
+static Lisp_Object
 status_convert (w)
      WAITTYPE w;
 {
@@ -418,7 +429,7 @@ status_convert (w)
 /* Given a status-list, extract the three pieces of information
    and store them individually through the three pointers.  */
 
-void
+static void
 decode_status (l, symbol, code, coredump)
      Lisp_Object l;
      Lisp_Object *symbol;
@@ -497,7 +508,7 @@ status_message (p)
    The file name of the terminal corresponding to the pty
    is left in the variable pty_name.  */
 
-int
+static int
 allocate_pty ()
 {
   register int c, i;
@@ -582,7 +593,7 @@ allocate_pty ()
 }
 #endif /* HAVE_PTYS */
 \f
-Lisp_Object
+static Lisp_Object
 make_process (name)
      Lisp_Object name;
 {
@@ -626,7 +637,7 @@ make_process (name)
   return val;
 }
 
-void
+static void
 remove_process (proc)
      register Lisp_Object proc;
 {
@@ -760,23 +771,27 @@ nil, indicating the current buffer's process.  */)
      (process)
      register Lisp_Object process;
 {
+  register struct Lisp_Process *p;
+
   process = get_process (process);
-  XPROCESS (process)->raw_status_low = Qnil;
-  XPROCESS (process)->raw_status_high = Qnil;
-  if (NETCONN_P (process))
+  p = XPROCESS (process);
+
+  p->raw_status_low = Qnil;
+  p->raw_status_high = Qnil;
+  if (NETCONN1_P (p))
     {
-      XPROCESS (process)->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
-      XSETINT (XPROCESS (process)->tick, ++process_tick);
-      status_notify ();
+      p->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
+      XSETINT (p->tick, ++process_tick);
+      status_notify (p);
     }
-  else if (XINT (XPROCESS (process)->infd) >= 0)
+  else if (XINT (p->infd) >= 0)
     {
       Fkill_process (process, Qnil);
       /* Do this now, since remove_process will make sigchld_handler do nothing.  */
-      XPROCESS (process)->status
+      p->status
        = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
-      XSETINT (XPROCESS (process)->tick, ++process_tick);
-      status_notify ();
+      XSETINT (p->tick, ++process_tick);
+      status_notify (p);
     }
   remove_process (process);
   return Qnil;
@@ -1230,7 +1245,7 @@ IP address.  Returns nil if format of ADDRESS is invalid.  */)
 }
 #endif
 \f
-Lisp_Object
+static Lisp_Object
 list_processes_1 (query_only)
      Lisp_Object query_only;
 {
@@ -1284,7 +1299,7 @@ list_processes_1 (query_only)
   XSETFASTINT (minspace, 1);
 
   set_buffer_internal (XBUFFER (Vstandard_output));
-  Fbuffer_disable_undo (Vstandard_output);
+  current_buffer->undo_list = Qt;
 
   current_buffer->truncate_lines = Qt;
 
@@ -1530,7 +1545,6 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
 
   XPROCESS (proc)->childp = Qt;
   XPROCESS (proc)->plist = Qnil;
-  XPROCESS (proc)->command_channel_p = Qnil;
   XPROCESS (proc)->buffer = buffer;
   XPROCESS (proc)->sentinel = Qnil;
   XPROCESS (proc)->filter = Qnil;
@@ -1701,7 +1715,7 @@ start_process_unwind (proc)
   return Qnil;
 }
 
-void
+static void
 create_process_1 (timer)
      struct atimer *timer;
 {
@@ -2524,7 +2538,7 @@ OPTION is not a supported option, return nil instead; otherwise return t.  */)
 \f
 /* A version of request_sigio suitable for a record_unwind_protect.  */
 
-Lisp_Object
+static Lisp_Object
 unwind_request_sigio (dummy)
      Lisp_Object dummy;
 {
@@ -2546,7 +2560,7 @@ DEFUN ("make-network-process", Fmake_network_process, Smake_network_process,
 In Emacs, network connections are represented by process objects, so
 input and output work as for subprocesses and `delete-process' closes
 a network connection.  However, a network process has no process id,
-it cannot be signalled, and the status codes are different from normal
+it cannot be signaled, and the status codes are different from normal
 processes.
 
 Arguments are specified as keyword/argument pairs.  The following
@@ -2716,7 +2730,6 @@ usage: (make-network-process &rest ARGS)  */)
   int xerrno = 0;
   int s = -1, outch, inch;
   struct gcpro gcpro1;
-  int retry = 0;
   int count = SPECPDL_INDEX ();
   int count1;
   Lisp_Object QCaddress;  /* one of QClocal or QCremote */
@@ -3017,6 +3030,8 @@ usage: (make-network-process &rest ARGS)  */)
     {
       int optn, optbits;
 
+    retry_connect:
+
       s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol);
       if (s < 0)
        {
@@ -3095,8 +3110,6 @@ usage: (make-network-process &rest ARGS)  */)
          break;
        }
 
-    retry_connect:
-
       immediate_quit = 1;
       QUIT;
 
@@ -3138,22 +3151,13 @@ usage: (make-network-process &rest ARGS)  */)
 
       immediate_quit = 0;
 
-      if (xerrno == EINTR)
-       goto retry_connect;
-      if (xerrno == EADDRINUSE && retry < 20)
-       {
-         /* A delay here is needed on some FreeBSD systems,
-            and it is harmless, since this retrying takes time anyway
-            and should be infrequent.  */
-         Fsleep_for (make_number (1), Qnil);
-         retry++;
-         goto retry_connect;
-       }
-
       /* Discard the unwind protect closing S.  */
       specpdl_ptr = specpdl + count1;
       emacs_close (s);
       s = -1;
+
+      if (xerrno == EINTR)
+       goto retry_connect;
     }
 
   if (s >= 0)
@@ -3672,12 +3676,14 @@ deactivate_process (proc)
       chan_process[inchannel] = Qnil;
       FD_CLR (inchannel, &input_wait_mask);
       FD_CLR (inchannel, &non_keyboard_wait_mask);
+#ifdef NON_BLOCKING_CONNECT
       if (FD_ISSET (inchannel, &connect_wait_mask))
        {
          FD_CLR (inchannel, &connect_wait_mask);
          if (--num_pending_connects < 0)
            abort ();
        }
+#endif
       if (inchannel == max_process_desc)
        {
          int i;
@@ -4038,8 +4044,11 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
 {
   register int channel, nfds;
   SELECT_TYPE Available;
+#ifdef NON_BLOCKING_CONNECT
   SELECT_TYPE Connecting;
-  int check_connect, check_delay, no_avail;
+  int check_connect;
+#endif
+  int check_delay, no_avail;
   int xerrno;
   Lisp_Object proc;
   EMACS_TIME timeout, end_time;
@@ -4050,7 +4059,9 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
   int saved_waiting_for_user_input_p = waiting_for_user_input_p;
 
   FD_ZERO (&Available);
+#ifdef NON_BLOCKING_CONNECT
   FD_ZERO (&Connecting);
+#endif
 
   /* If wait_proc is a process to watch, set wait_channel accordingly.  */
   if (wait_proc != NULL)
@@ -4187,7 +4198,10 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
         timeout to get our attention.  */
       if (update_tick != process_tick && do_display)
        {
-         SELECT_TYPE Atemp, Ctemp;
+         SELECT_TYPE Atemp;
+#ifdef NON_BLOCKING_CONNECT
+         SELECT_TYPE Ctemp;
+#endif
 
          Atemp = input_wait_mask;
 #if 0
@@ -4199,18 +4213,23 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
          */
           FD_CLR (0, &Atemp);
 #endif
-         Ctemp = connect_wait_mask;
+         IF_NON_BLOCKING_CONNECT (Ctemp = connect_wait_mask);
+
          EMACS_SET_SECS_USECS (timeout, 0, 0);
          if ((select (max (max_process_desc, max_keyboard_desc) + 1,
                       &Atemp,
+#ifdef NON_BLOCKING_CONNECT
                       (num_pending_connects > 0 ? &Ctemp : (SELECT_TYPE *)0),
+#else
+                      (SELECT_TYPE *)0,
+#endif
                       (SELECT_TYPE *)0, &timeout)
               <= 0))
            {
              /* It's okay for us to do this and then continue with
                 the loop, since timeout has already been zeroed out.  */
              clear_waiting_for_input ();
-             status_notify ();
+             status_notify (NULL);
            }
        }
 
@@ -4263,12 +4282,14 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
          if (XINT (wait_proc->infd) < 0)  /* Terminated */
            break;
          FD_SET (XINT (wait_proc->infd), &Available);
-         check_connect = check_delay = 0;
+         check_delay = 0;
+         IF_NON_BLOCKING_CONNECT (check_connect = 0);
        }
       else if (!NILP (wait_for_cell))
        {
          Available = non_process_wait_mask;
-         check_connect = check_delay = 0;
+         check_delay = 0;
+         IF_NON_BLOCKING_CONNECT (check_connect = 0);
        }
       else
        {
@@ -4276,7 +4297,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
            Available = non_keyboard_wait_mask;
          else
            Available = input_wait_mask;
-         check_connect = (num_pending_connects > 0);
+         IF_NON_BLOCKING_CONNECT (check_connect = (num_pending_connects > 0));
          check_delay = wait_channel >= 0 ? 0 : process_output_delay_count;
        }
 
@@ -4301,10 +4322,17 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
        }
       else
        {
+#ifdef NON_BLOCKING_CONNECT
          if (check_connect)
            Connecting = connect_wait_mask;
+#endif
 
 #ifdef ADAPTIVE_READ_BUFFERING
+         /* Set the timeout for adaptive read buffering if any
+            process has non-nil read_output_skip and non-zero
+            read_output_delay, and we are not reading output for a
+            specific wait_channel.  It is not executed if
+            Vprocess_adaptive_read_buffering is nil.  */
          if (process_output_skip && check_delay > 0)
            {
              int usecs = EMACS_USECS (timeout);
@@ -4315,6 +4343,8 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
                  proc = chan_process[channel];
                  if (NILP (proc))
                    continue;
+                 /* Find minimum non-zero read_output_delay among the
+                    processes with non-nil read_output_skip.  */
                  if (XINT (XPROCESS (proc)->read_output_delay) > 0)
                    {
                      check_delay--;
@@ -4333,7 +4363,11 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
 
          nfds = select (max (max_process_desc, max_keyboard_desc) + 1,
                         &Available,
+#ifdef NON_BLOCKING_CONNECT
                         (check_connect ? &Connecting : (SELECT_TYPE *)0),
+#else
+                        (SELECT_TYPE *)0,
+#endif
                         (SELECT_TYPE *)0, &timeout);
        }
 
@@ -4389,7 +4423,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
       if (no_avail)
        {
          FD_ZERO (&Available);
-         check_connect = 0;
+         IF_NON_BLOCKING_CONNECT (check_connect = 0);
        }
 
 #if defined(sun) && !defined(USG5_4)
@@ -4713,7 +4747,7 @@ read_process_output_error_handler (error)
    The characters read are decoded according to PROC's coding-system
    for decoding.  */
 
-int
+static int
 read_process_output (proc, channel)
      Lisp_Object proc;
      register int channel;
@@ -4861,10 +4895,10 @@ read_process_output (proc, channel)
        {
          Lisp_Object tem;
          /* Don't clobber the CURRENT match data, either!  */
-         tem = Fmatch_data (Qnil, Qnil);
-         restore_match_data ();
-         record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
-         Fset_match_data (tem);
+         tem = Fmatch_data (Qnil, Qnil, Qnil);
+         restore_search_regs ();
+         record_unwind_save_match_data ();
+         Fset_match_data (tem, Qt);
        }
 
       /* For speed, if a search happens within this code,
@@ -4918,7 +4952,7 @@ read_process_output (proc, channel)
                                   read_process_output_error_handler);
 
       /* If we saved the match data nonrecursively, restore it now.  */
-      restore_match_data ();
+      restore_search_regs ();
       running_asynch_code = outer_running_asynch_code;
 
       /* Handling the process output should not deactivate the mark.  */
@@ -5085,10 +5119,12 @@ Lisp_Object process_sent_to;
 SIGTYPE
 send_process_trap ()
 {
+  SIGNAL_THREAD_CHECK (SIGPIPE);
 #ifdef BSD4_1
   sigrelse (SIGPIPE);
   sigrelse (SIGALRM);
 #endif /* BSD4_1 */
+  sigunblock (sigmask (SIGPIPE));
   longjmp (send_process_frame, 1);
 }
 
@@ -5102,7 +5138,7 @@ send_process_trap ()
 
    This function can evaluate Lisp code and can garbage collect.  */
 
-void
+static void
 send_process (proc, buf, len, object)
      volatile Lisp_Object proc;
      unsigned char *volatile buf;
@@ -5114,6 +5150,7 @@ send_process (proc, buf, len, object)
   int rv;
   struct coding_system *coding;
   struct gcpro gcpro1;
+  SIGTYPE (*volatile old_sigpipe) ();
 
   GCPRO1 (object);
 
@@ -5238,7 +5275,6 @@ send_process (proc, buf, len, object)
       while (len > 0)
        {
          int this = len;
-         SIGTYPE (*old_sigpipe)();
 
          /* Decide how much data we can send in one batch.
             Long lines need to be split into multiple batches.  */
@@ -5280,7 +5316,11 @@ send_process (proc, buf, len, object)
                               0, datagram_address[outfd].sa,
                               datagram_address[outfd].len);
                  if (rv < 0 && errno == EMSGSIZE)
-                   report_file_error ("sending datagram", Fcons (proc, Qnil));
+                   {
+                     signal (SIGPIPE, old_sigpipe);
+                     report_file_error ("sending datagram",
+                                        Fcons (proc, Qnil));
+                   }
                }
              else
 #endif
@@ -5377,6 +5417,7 @@ send_process (proc, buf, len, object)
 #endif /* not VMS */
   else
     {
+      signal (SIGPIPE, old_sigpipe);
 #ifndef VMS
       proc = process_sent_to;
       p = XPROCESS (proc);
@@ -5691,7 +5732,7 @@ process_send_signal (process, signo, current_group, nomsg)
       p->status = Qrun;
       XSETINT (p->tick, ++process_tick);
       if (!nomsg)
-       status_notify ();
+       status_notify (NULL);
       break;
 #endif /* ! defined (SIGCONT) */
     case SIGINT:
@@ -5802,7 +5843,7 @@ If PROCESS is a network process, inhibit handling of incoming traffic.  */)
     }
 #endif
 #ifndef SIGTSTP
-  error ("no SIGTSTP support");
+  error ("No SIGTSTP support");
 #else
   process_send_signal (process, SIGTSTP, current_group, 0);
 #endif
@@ -5836,7 +5877,7 @@ If PROCESS is a network process, resume handling of incoming traffic.  */)
 #ifdef SIGCONT
     process_send_signal (process, SIGCONT, current_group, 0);
 #else
-    error ("no SIGCONT support");
+    error ("No SIGCONT support");
 #endif
   return process;
 }
@@ -6127,6 +6168,8 @@ sigchld_handler (signo)
   register struct Lisp_Process *p;
   extern EMACS_TIME *input_available_clear_time;
 
+  SIGNAL_THREAD_CHECK (signo);
+
 #ifdef BSD4_1
   extern int sigheld;
   sigheld |= sigbit (SIGCHLD);
@@ -6313,10 +6356,10 @@ exec_sentinel (proc, reason)
   if (outer_running_asynch_code)
     {
       Lisp_Object tem;
-      tem = Fmatch_data (Qnil, Qnil);
-      restore_match_data ();
-      record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
-      Fset_match_data (tem);
+      tem = Fmatch_data (Qnil, Qnil, Qnil);
+      restore_search_regs ();
+      record_unwind_save_match_data ();
+      Fset_match_data (tem, Qt);
     }
 
   /* For speed, if a search happens within this code,
@@ -6330,7 +6373,7 @@ exec_sentinel (proc, reason)
                             exec_sentinel_error_handler);
 
   /* If we saved the match data nonrecursively, restore it now.  */
-  restore_match_data ();
+  restore_search_regs ();
   running_asynch_code = outer_running_asynch_code;
 
   Vdeactivate_mark = odeactivate;
@@ -6357,8 +6400,9 @@ exec_sentinel (proc, reason)
    This is usually done while Emacs is waiting for keyboard input
    but can be done at other times.  */
 
-void
-status_notify ()
+static void
+status_notify (deleting_process)
+     struct Lisp_Process *deleting_process;
 {
   register Lisp_Object proc, buffer;
   Lisp_Object tail, msg;
@@ -6394,6 +6438,7 @@ status_notify ()
                 && ! EQ (p->status, Qlisten)
                 && ! EQ (p->command, Qt)  /* Network process not stopped.  */
                 && XINT (p->infd) >= 0
+                && p != deleting_process
                 && read_process_output (proc, XINT (p->infd)) > 0);
 
          buffer = p->buffer;
@@ -6597,7 +6642,7 @@ delete_keyboard_wait_descriptor (desc)
 /* Return nonzero if *MASK has a bit set
    that corresponds to one of the keyboard input descriptors.  */
 
-int
+static int
 keyboard_bit_set (mask)
      SELECT_TYPE *mask;
 {
@@ -6628,6 +6673,11 @@ init_process ()
   FD_ZERO (&non_process_wait_mask);
   max_process_desc = 0;
 
+#ifdef NON_BLOCKING_CONNECT
+  FD_ZERO (&connect_wait_mask);
+  num_pending_connects = 0;
+#endif
+
 #ifdef ADAPTIVE_READ_BUFFERING
   process_output_delay_count = 0;
   process_output_skip = 0;
@@ -6677,6 +6727,19 @@ init_process ()
    Fprovide (intern ("make-network-process"), subfeatures);
  }
 #endif /* HAVE_SOCKETS */
+
+#if defined (DARWIN) || defined (MAC_OSX)
+  /* PTYs are broken on Darwin < 6, but are sometimes useful for interactive
+     processes.  As such, we only change the default value.  */
+ if (initialized)
+  {
+    char *release = get_operating_system_release();
+    if (!release || !release[0] || (release[0] < MIN_PTY_KERNEL_VERSION
+                                   && release[1] == '.')) {
+      Vprocess_connection_type = Qnil;
+    }
+  }
+#endif
 }
 
 void
@@ -6771,7 +6834,7 @@ The value takes effect when `start-process' is called.  */);
               doc: /* If non-nil, improve receive buffering by delaying after short reads.
 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 behaviour can be remedied to some extent by setting this variable to a
+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.
 If the value is t, the delay is reset after each write to the process; any other