merge from gcc

This commit is contained in:
DJ Delorie 2004-03-18 04:07:41 +00:00
parent e0c148a751
commit 12a7367e81
3 changed files with 72 additions and 16 deletions

View File

@ -1,5 +1,9 @@
2004-03-17 Ian Lance Taylor <ian@wasabisystems.com>
* pex-unix.c (pexecute): Use vfork instead of fork, with
appropriate changes to make this safe.
* pex-common.h (STDERR_FILE_NO): Define.
* Makefile.in: Clean up REQUIRED_OFILES and CONFIGURED_OFILES for
an 80 column screen. Run maint-deps.

View File

@ -1,6 +1,6 @@
/* Utilities to execute a program in a subprocess (possibly linked by pipes
with other subprocesses), and wait for it. Shared logic.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
Free Software Foundation, Inc.
This file is part of the libiberty library.
@ -33,6 +33,9 @@ Boston, MA 02111-1307, USA. */
/* stdout file number. */
#define STDOUT_FILE_NO 1
/* stderr file number. */
#define STDERR_FILE_NO 2
/* value of `pipe': port index for reading. */
#define READ_PORT 0

View File

@ -1,7 +1,7 @@
/* Utilities to execute a program in a subprocess (possibly linked by pipes
with other subprocesses), and wait for it. Generic Unix version
(also used for UWIN and VMS).
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
Free Software Foundation, Inc.
This file is part of the libiberty library.
@ -44,28 +44,66 @@ extern int errno;
#define waitpid(pid, status, flags) wait(status)
#endif
extern int execv ();
extern int execvp ();
#ifdef vfork /* Autoconf may define this to fork for us. */
# define VFORK_STRING "fork"
#else
# define VFORK_STRING "vfork"
#endif
#ifdef HAVE_VFORK_H
#include <vfork.h>
#endif
#ifdef VMS
#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
#endif /* VMS */
/* Execute a program, possibly setting up pipes to programs executed
via other calls to this function.
This version of the function uses vfork. In general vfork is
similar to setjmp/longmp, in that any variable which is modified by
the child process has an indeterminate value in the parent process.
We follow a safe approach here by not modifying any variables at
all in the child process (with the possible exception of variables
modified by xstrerror if exec fails, but this is unlikely to be
detectable).
We work a little bit harder to avoid gcc warnings. gcc will warn
about any automatic variable which is live at the time of the
vfork, which is non-volatile, and which is either set more than
once or is an argument to the function. This warning isn't quite
right, since what we really care about is whether the variable is
live at the time of the vfork and set afterward by the child
process, but gcc only checks whether the variable is set more than
once. To avoid this warning, we ensure that any variable which is
live at the time of the vfork (i.e., used after the vfork) is set
exactly once and is not an argument, or is marked volatile. */
int
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg,
flagsarg)
const char *program;
char * const *argv;
const char *this_pname;
const char *temp_base ATTRIBUTE_UNUSED;
char **errmsg_fmt, **errmsg_arg;
int flags;
int flagsarg;
{
int (*func)() = (flags & PEXECUTE_SEARCH ? execvp : execv);
int pid;
int pdes[2];
int out;
int input_desc, output_desc;
int retries, sleep_interval;
int flags;
/* We declare these to be volatile to avoid warnings from gcc about
them being clobbered by vfork. */
volatile int retries, sleep_interval;
/* 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;
flags = flagsarg;
/* If this is the first process, initialize. */
if (flags & PEXECUTE_FIRST)
last_pipe_input = STDIN_FILE_NO;
@ -82,22 +120,24 @@ pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
*errmsg_arg = NULL;
return -1;
}
output_desc = pdes[WRITE_PORT];
out = pdes[WRITE_PORT];
last_pipe_input = pdes[READ_PORT];
}
else
{
/* Last process. */
output_desc = STDOUT_FILE_NO;
out = STDOUT_FILE_NO;
last_pipe_input = STDIN_FILE_NO;
}
output_desc = out;
/* Fork a subprocess; wait and retry if it fails. */
sleep_interval = 1;
pid = -1;
for (retries = 0; retries < 4; retries++)
{
pid = fork ();
pid = vfork ();
if (pid >= 0)
break;
sleep (sleep_interval);
@ -131,12 +171,21 @@ pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
close (last_pipe_input);
/* Exec the program. */
(*func) (program, argv);
if (flags & PEXECUTE_SEARCH)
execvp (program, argv);
else
execv (program, argv);
fprintf (stderr, "%s: ", this_pname);
fprintf (stderr, install_error_msg, program);
fprintf (stderr, ": %s\n", xstrerror (errno));
exit (-1);
/* We don't want to call fprintf after vfork. */
#define writeerr(s) write (STDERR_FILE_NO, s, strlen (s))
writeerr (this_pname);
writeerr (": ");
writeerr ("installation problem, cannot exec '");
writeerr (program);
writeerr ("': ");
writeerr (xstrerror (errno));
writeerr ("\n");
_exit (-1);
/* NOTREACHED */
return 0;