This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

use posix_spawn in pexecute


This patch to libiberty makes the `pexecute' function use the POSIX.1
<spawn.h> interfaces (`posix_spawn' or `posix_spawnp') instead of fork and
exec, when configure finds the <spawn.h> functions available.

This interface is available on all GNU systems with GNU libc 2.2 and later.
I don't know if other systems support it yet as well.  The existing GNU
implementations just use fork and exec and so the sequence of calls is in
fact nearly identical to the old pexecute code.  But using the posix_spawn
interface makes it possible for the system library to further optimize this
without any more source changes in libiberty.  (We expect that a library
version in the near future will have a different and lower-overhead
implementation on GNU/Hurd, for example.)

I haven't done any kind of exhaustive testing, but this certainly appears
to work fine on a GNU/Linux host.  

Here is a log entry and patch for libiberty as in the gcc repository today.
I've omitted patches for files produced by autoconf and autoheader.

Thanks,
Roland


2001-12-16  Roland McGrath  <roland@frob.com>

	* configure.in: Check for spawn.h and posix_spawnp.
	* pexecute.c [HAVE_POSIX_SPAWNP] (pexecute): New implementation
	using POSIX.1 <spawn.h> interface instead of fork and exec.

Index: configure.in
===================================================================
RCS file: /cvs/gcc/gcc/libiberty/configure.in,v
retrieving revision 1.42
diff -c -3 -p -b -r1.42 configure.in
*** configure.in	2001/12/11 12:17:33	1.42
--- configure.in	2001/12/17 00:40:15
*************** AC_SUBST_FILE(host_makefile_frag)
*** 120,126 ****
  # It's OK to check for header files.  Although the compiler may not be
  # able to link anything, it had better be able to at least compile
  # something.
! AC_CHECK_HEADERS(sys/file.h sys/param.h limits.h stdlib.h string.h unistd.h strings.h sys/time.h time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h alloca.h)
  AC_HEADER_SYS_WAIT
  AC_HEADER_TIME
  
--- 120,126 ----
  # It's OK to check for header files.  Although the compiler may not be
  # able to link anything, it had better be able to at least compile
  # something.
! AC_CHECK_HEADERS(sys/file.h sys/param.h limits.h stdlib.h string.h unistd.h strings.h sys/time.h time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h alloca.h spawn.h)
  AC_HEADER_SYS_WAIT
  AC_HEADER_TIME
  
*************** funcs="$funcs waitpid"
*** 187,193 ****
  
  vars="sys_errlist sys_nerr sys_siglist"
  
! checkfuncs="getrusage on_exit psignal strerror strsignal sysconf times sbrk gettimeofday"
  
  # These are neither executed nor required, but they help keep
  # autoheader happy without adding a bunch of text to acconfig.h.
--- 187,193 ----
  
  vars="sys_errlist sys_nerr sys_siglist"
  
! checkfuncs="getrusage on_exit psignal strerror strsignal sysconf times sbrk gettimeofday posix_spawnp"
  
  # These are neither executed nor required, but they help keep
  # autoheader happy without adding a bunch of text to acconfig.h.
*************** if test "x" = "y"; then
*** 198,204 ****
    AC_CHECK_FUNCS(strcasecmp setenv strchr strdup strncasecmp strrchr strstr)
    AC_CHECK_FUNCS(strtod strtol strtoul tmpnam vasprintf vfprintf vprintf)
    AC_CHECK_FUNCS(vsprintf waitpid getrusage on_exit psignal strerror strsignal)
!   AC_CHECK_FUNCS(sysconf times sbrk gettimeofday ffs)
    AC_DEFINE(HAVE_SYS_ERRLIST, 1, [Define if you have the sys_errlist variable.])
    AC_DEFINE(HAVE_SYS_NERR,    1, [Define if you have the sys_nerr variable.])
    AC_DEFINE(HAVE_SYS_SIGLIST, 1, [Define if you have the sys_siglist variable.])
--- 198,204 ----
    AC_CHECK_FUNCS(strcasecmp setenv strchr strdup strncasecmp strrchr strstr)
    AC_CHECK_FUNCS(strtod strtol strtoul tmpnam vasprintf vfprintf vprintf)
    AC_CHECK_FUNCS(vsprintf waitpid getrusage on_exit psignal strerror strsignal)
!   AC_CHECK_FUNCS(sysconf times sbrk gettimeofday ffs posix_spawnp)
    AC_DEFINE(HAVE_SYS_ERRLIST, 1, [Define if you have the sys_errlist variable.])
    AC_DEFINE(HAVE_SYS_NERR,    1, [Define if you have the sys_nerr variable.])
    AC_DEFINE(HAVE_SYS_SIGLIST, 1, [Define if you have the sys_siglist variable.])
Index: pexecute.c
===================================================================
RCS file: /cvs/gcc/gcc/libiberty/pexecute.c,v
retrieving revision 1.23
diff -c -3 -p -b -r1.23 pexecute.c
*** pexecute.c	2001/10/17 21:15:41	1.23
--- pexecute.c	2001/12/17 00:40:15
***************
*** 1,6 ****
  /* Utilities to execute a program in a subprocess (possibly linked by pipes
     with other subprocesses), and wait for it.
!    Copyright (C) 1996-2000 Free Software Foundation, Inc.
  
  This file is part of the libiberty library.
  Libiberty is free software; you can redistribute it and/or
--- 1,6 ----
  /* Utilities to execute a program in a subprocess (possibly linked by pipes
     with other subprocesses), and wait for it.
!    Copyright (C) 1996-2001 Free Software Foundation, Inc.
  
  This file is part of the libiberty library.
  Libiberty is free software; you can redistribute it and/or
*************** extern int errno;
*** 44,49 ****
--- 44,52 ----
  #ifdef HAVE_SYS_WAIT_H
  #include <sys/wait.h>
  #endif
+ #if defined(HAVE_SPAWN_H) && defined(HAVE_POSIX_SPAWNP)
+ #include <spawn.h>
+ #endif
  
  #include "libiberty.h"
  #include "safe-ctype.h"
*************** pfinish ()
*** 664,669 ****
--- 667,674 ----
  #if ! defined (__MSDOS__) && ! defined (OS2) && ! defined (MPW) \
      && ! (defined (_WIN32) && ! defined (_UWIN))
  
+ # ifndef HAVE_POSIX_SPAWNP
+ 
  extern int execv ();
  extern int execvp ();
  
*************** pexecute (program, argv, this_pname, tem
*** 772,777 ****
--- 777,872 ----
        return pid;
      }
  }
+ 
+ # else
+ 
+ extern char **environ;
+ 
+ int
+ pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
+      const char *program;
+      char * const *argv;
+      const char *this_pname ATTRIBUTE_UNUSED;
+      const char *temp_base ATTRIBUTE_UNUSED;
+      char **errmsg_fmt, **errmsg_arg;
+      int flags;
+ {
+   pid_t pid;
+   int pdes[2];
+   int input_desc, output_desc;
+   /* Pipe waiting from last process, to be used as input for the next one.
+      Value is STDIN_FILE_NO if no pipe is waiting
+      (i.e. the next command is the first of a group).  */
+   static int last_pipe_input;
+   posix_spawn_file_actions_t fa;
+   int error;
+ 
+   /* If this is the first process, initialize.  */
+   if (flags & PEXECUTE_FIRST)
+     last_pipe_input = STDIN_FILE_NO;
+ 
+   input_desc = last_pipe_input;
+ 
+   /* If this isn't the last process, make a pipe for its output,
+      and record it as waiting to be the input to the next process.  */
+   if (! (flags & PEXECUTE_LAST))
+     {
+       if (pipe (pdes) < 0)
+ 	{
+ 	  *errmsg_fmt = "pipe";
+ 	  *errmsg_arg = NULL;
+ 	  return -1;
+ 	}
+       output_desc = pdes[WRITE_PORT];
+       last_pipe_input = pdes[READ_PORT];
+     }
+   else
+     {
+       /* Last process.  */
+       output_desc = STDOUT_FILE_NO;
+       last_pipe_input = STDIN_FILE_NO;
+     }
+ 
+   *errmsg_fmt = "posix_spawn_file_actions_init";
+   *errmsg_arg = NULL;
+   error = posix_spawn_file_actions_init (&fa);
+   if (error == 0)
+     {
+       *errmsg_fmt = "posix_spawn_file_actions_adddup2";
+       error = posix_spawn_file_actions_adddup2 (&fa,
+ 						input_desc, STDIN_FILE_NO);
+       if (error == 0)
+ 	error = posix_spawn_file_actions_adddup2 (&fa,
+ 						  output_desc, STDOUT_FILE_NO);
+       *errmsg_fmt = "posix_spawn_file_actions_addclose";
+       if (error == 0 && last_pipe_input != STDIN_FILE_NO)
+ 	error = posix_spawn_file_actions_addclose (&fa, last_pipe_input);
+       if (error == 0)
+ 	{
+ 	  error = (flags & PEXECUTE_SEARCH ? posix_spawnp : posix_spawn)
+ 	    (&pid, program, &fa, (const posix_spawnattr_t *)0, argv, environ);
+ 	  *errmsg_fmt = install_error_msg;
+ 	  *errmsg_arg = (char *)program;
+ 	}
+     }
+   posix_spawn_file_actions_destroy (&fa);
+ 
+   /* Close the descriptors that we made for this child.  */
+   if (input_desc != STDIN_FILE_NO)
+     close (input_desc);
+   if (output_desc != STDOUT_FILE_NO)
+     close (output_desc);
+ 
+   if (error != 0)
+     {
+       errno = error;
+       return -1;
+     }
+ 
+   return (int)pid;
+ }
+ 
+ # endif
  
  int
  pwait (pid, status, flags)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]