]> code.delx.au - gnu-emacs/blobdiff - src/sysdep.c
Merge from emacs-24; up to 2012-12-06T01:39:03Z!monnier@iro.umontreal.ca
[gnu-emacs] / src / sysdep.c
index 960c13b8d84eeab4d7ef671efad3fa3af56be6dc..049eb85afe5090e8ac071f54577e714776e82101 100644 (file)
@@ -101,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"
@@ -134,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
@@ -155,7 +154,6 @@ get_current_dir_name (void)
         return NULL;
       strcpy (buf, pwd);
     }
-#ifdef HAVE_GETCWD
   else
     {
       size_t buf_size = 1024;
@@ -179,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
@@ -284,48 +266,74 @@ init_baud_rate (int fd)
 
 #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)
-    {
-#ifdef WINDOWSNT
-      wait (0);
-      break;
-#else /* not WINDOWSNT */
-      int status;
-      int wait_result = waitpid (pid, &status, 0);
-      if (wait_result < 0)
-       {
-         if (errno != EINTR)
-           break;
-       }
-      else
-       {
-         record_child_status_change (wait_result, status);
-         break;
-       }
+  pid_t pid;
 
-#endif /* not WINDOWSNT */
+  /* 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);
 }
 
 /*
@@ -449,20 +457,15 @@ static void restore_signal_handlers (struct save_signal *);
 void
 sys_suspend (void)
 {
-#if defined (SIGTSTP) && !defined (MSDOS)
-
-  {
-    pid_t 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.  */
@@ -474,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;
@@ -512,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)
@@ -524,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
@@ -581,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
@@ -709,7 +710,7 @@ static pid_t inherited_pgroup;
 void
 init_foreground_group (void)
 {
-  pid_t pgrp = EMACS_GETPGRP (0);
+  pid_t pgrp = getpgrp ();
   inherited_pgroup = getpid () == pgrp ? 0 : pgrp;
 }
 
@@ -1039,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)] =
@@ -1058,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.
@@ -1278,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));
@@ -1287,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),
@@ -1516,9 +1513,7 @@ emacs_sigaction_init (struct sigaction *action, signal_handler_t handler)
   /* When handling a signal, block nonfatal system signals that are caught
      by Emacs.  This makes race conditions less likely.  */
   sigaddset (&action->sa_mask, SIGALRM);
-#ifdef SIGCHLD
   sigaddset (&action->sa_mask, SIGCHLD);
-#endif
 #ifdef SIGDANGER
   sigaddset (&action->sa_mask, SIGDANGER);
 #endif
@@ -1698,18 +1693,11 @@ init_signals (bool dumping)
 # 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
@@ -1729,9 +1717,7 @@ init_signals (bool dumping)
 # ifdef SIGGRANT
       sys_siglist[SIGGRANT] = "Monitor mode granted";
 # endif
-# ifdef SIGHUP
       sys_siglist[SIGHUP] = "Hangup";
-# endif
       sys_siglist[SIGILL] = "Illegal instruction";
       sys_siglist[SIGINT] = "Interrupt";
 # ifdef SIGIO
@@ -1743,9 +1729,7 @@ init_signals (bool dumping)
 # ifdef SIGIOT
       sys_siglist[SIGIOT] = "IOT trap";
 # endif
-# ifdef SIGKILL
       sys_siglist[SIGKILL] = "Killed";
-# endif
 # ifdef SIGLOST
       sys_siglist[SIGLOST] = "Resource lost";
 # endif
@@ -1758,9 +1742,7 @@ init_signals (bool dumping)
 # ifdef SIGPHONE
       sys_siglist[SIGWIND] = "SIGPHONE";
 # endif
-# ifdef SIGPIPE
       sys_siglist[SIGPIPE] = "Broken pipe";
-# endif
 # ifdef SIGPOLL
       sys_siglist[SIGPOLL] = "Pollable event occurred";
 # endif
@@ -1773,9 +1755,7 @@ init_signals (bool dumping)
 # 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
@@ -2130,7 +2110,7 @@ emacs_backtrace (int backtrace_limit)
 void
 emacs_abort (void)
 {
-  terminate_due_to_signal (SIGABRT, 10);
+  terminate_due_to_signal (SIGABRT, 40);
 }
 #endif
 
@@ -2244,82 +2224,6 @@ emacs_readlink (char const *filename, char initial_buf[READLINK_BUFSIZE])
   return careadlinkat (AT_FDCWD, filename, 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) */
-#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.
@@ -2380,19 +2284,7 @@ safe_strsignal (int code)
 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",