mirror of git://gcc.gnu.org/git/gcc.git
[libiberty patch] PEX-unix forking
https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01170.html * pex-unix.c (pex_child_error): Delete. (pex_unix_exec_child): Commonize error paths to single message & exit. From-SVN: r263679
This commit is contained in:
parent
a7e94dc09a
commit
5c12a85534
|
@ -1,3 +1,9 @@
|
||||||
|
2018-08-20 Nathan Sidwell <nathan@acm.org>
|
||||||
|
|
||||||
|
* pex-unix.c (pex_child_error): Delete.
|
||||||
|
(pex_unix_exec_child): Commonize error paths to single message &
|
||||||
|
exit.
|
||||||
|
|
||||||
2018-07-30 Tom Tromey <tom@tromey.com>
|
2018-07-30 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
* cplus-dem.c (remember_Btype): Don't call memcpy with LEN==0.
|
* cplus-dem.c (remember_Btype): Don't call memcpy with LEN==0.
|
||||||
|
|
|
@ -298,8 +298,6 @@ pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time)
|
||||||
#endif /* ! defined (HAVE_WAITPID) */
|
#endif /* ! defined (HAVE_WAITPID) */
|
||||||
#endif /* ! defined (HAVE_WAIT4) */
|
#endif /* ! defined (HAVE_WAIT4) */
|
||||||
|
|
||||||
static void pex_child_error (struct pex_obj *, const char *, const char *, int)
|
|
||||||
ATTRIBUTE_NORETURN;
|
|
||||||
static int pex_unix_open_read (struct pex_obj *, const char *, int);
|
static int pex_unix_open_read (struct pex_obj *, const char *, int);
|
||||||
static int pex_unix_open_write (struct pex_obj *, const char *, int, int);
|
static int pex_unix_open_write (struct pex_obj *, const char *, int, int);
|
||||||
static pid_t pex_unix_exec_child (struct pex_obj *, int, const char *,
|
static pid_t pex_unix_exec_child (struct pex_obj *, int, const char *,
|
||||||
|
@ -366,28 +364,6 @@ pex_unix_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
|
||||||
return close (fd);
|
return close (fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Report an error from a child process. We don't use stdio routines,
|
|
||||||
because we might be here due to a vfork call. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
pex_child_error (struct pex_obj *obj, const char *executable,
|
|
||||||
const char *errmsg, int err)
|
|
||||||
{
|
|
||||||
int retval = 0;
|
|
||||||
#define writeerr(s) retval |= (write (STDERR_FILE_NO, s, strlen (s)) < 0)
|
|
||||||
writeerr (obj->pname);
|
|
||||||
writeerr (": error trying to exec '");
|
|
||||||
writeerr (executable);
|
|
||||||
writeerr ("': ");
|
|
||||||
writeerr (errmsg);
|
|
||||||
writeerr (": ");
|
|
||||||
writeerr (xstrerror (err));
|
|
||||||
writeerr ("\n");
|
|
||||||
#undef writeerr
|
|
||||||
/* Exit with -2 if the error output failed, too. */
|
|
||||||
_exit (retval == 0 ? -1 : -2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Execute a child. */
|
/* Execute a child. */
|
||||||
|
|
||||||
#if defined(HAVE_SPAWNVE) && defined(HAVE_SPAWNVPE)
|
#if defined(HAVE_SPAWNVE) && defined(HAVE_SPAWNVPE)
|
||||||
|
@ -592,21 +568,22 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
|
||||||
int in, int out, int errdes,
|
int in, int out, int errdes,
|
||||||
int toclose, const char **errmsg, int *err)
|
int toclose, const char **errmsg, int *err)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid = -1;
|
||||||
|
|
||||||
/* We declare these to be volatile to avoid warnings from gcc about
|
/* We declare these to be volatile to avoid warnings from gcc about
|
||||||
them being clobbered by vfork. */
|
them being clobbered by vfork. */
|
||||||
volatile int sleep_interval;
|
volatile int sleep_interval = 1;
|
||||||
volatile int retries;
|
volatile int retries;
|
||||||
|
|
||||||
/* We vfork and then set environ in the child before calling execvp.
|
/* We vfork and then set environ in the child before calling execvp.
|
||||||
This clobbers the parent's environ so we need to restore it.
|
This clobbers the parent's environ so we need to restore it.
|
||||||
It would be nice to use one of the exec* functions that takes an
|
It would be nice to use one of the exec* functions that takes an
|
||||||
environment as a parameter, but that may have portability issues. */
|
environment as a parameter, but that may have portability
|
||||||
|
issues. */
|
||||||
char **save_environ = environ;
|
char **save_environ = environ;
|
||||||
|
|
||||||
sleep_interval = 1;
|
const char *bad_fn = NULL;
|
||||||
pid = -1;
|
|
||||||
for (retries = 0; retries < 4; ++retries)
|
for (retries = 0; retries < 4; ++retries)
|
||||||
{
|
{
|
||||||
pid = vfork ();
|
pid = vfork ();
|
||||||
|
@ -625,57 +602,76 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
/* Child process. */
|
/* Child process. */
|
||||||
if (in != STDIN_FILE_NO)
|
if (!bad_fn && in != STDIN_FILE_NO)
|
||||||
{
|
{
|
||||||
if (dup2 (in, STDIN_FILE_NO) < 0)
|
if (dup2 (in, STDIN_FILE_NO) < 0)
|
||||||
pex_child_error (obj, executable, "dup2", errno);
|
bad_fn = "dup2";
|
||||||
if (close (in) < 0)
|
else if (close (in) < 0)
|
||||||
pex_child_error (obj, executable, "close", errno);
|
bad_fn = "close";
|
||||||
}
|
}
|
||||||
if (out != STDOUT_FILE_NO)
|
if (!bad_fn && out != STDOUT_FILE_NO)
|
||||||
{
|
{
|
||||||
if (dup2 (out, STDOUT_FILE_NO) < 0)
|
if (dup2 (out, STDOUT_FILE_NO) < 0)
|
||||||
pex_child_error (obj, executable, "dup2", errno);
|
bad_fn = "dup2";
|
||||||
if (close (out) < 0)
|
else if (close (out) < 0)
|
||||||
pex_child_error (obj, executable, "close", errno);
|
bad_fn = "close";
|
||||||
}
|
}
|
||||||
if (errdes != STDERR_FILE_NO)
|
if (!bad_fn && errdes != STDERR_FILE_NO)
|
||||||
{
|
{
|
||||||
if (dup2 (errdes, STDERR_FILE_NO) < 0)
|
if (dup2 (errdes, STDERR_FILE_NO) < 0)
|
||||||
pex_child_error (obj, executable, "dup2", errno);
|
bad_fn = "dup2";
|
||||||
if (close (errdes) < 0)
|
else if (close (errdes) < 0)
|
||||||
pex_child_error (obj, executable, "close", errno);
|
bad_fn = "close";
|
||||||
}
|
}
|
||||||
if (toclose >= 0)
|
if (!bad_fn && toclose >= 0)
|
||||||
{
|
{
|
||||||
if (close (toclose) < 0)
|
if (close (toclose) < 0)
|
||||||
pex_child_error (obj, executable, "close", errno);
|
bad_fn = "close";
|
||||||
}
|
}
|
||||||
if ((flags & PEX_STDERR_TO_STDOUT) != 0)
|
if (!bad_fn && (flags & PEX_STDERR_TO_STDOUT) != 0)
|
||||||
{
|
{
|
||||||
if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
|
if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
|
||||||
pex_child_error (obj, executable, "dup2", errno);
|
bad_fn = "dup2";
|
||||||
|
}
|
||||||
|
if (!bad_fn)
|
||||||
|
{
|
||||||
|
if (env)
|
||||||
|
/* NOTE: In a standard vfork implementation this clobbers
|
||||||
|
the parent's copy of environ "too" (in reality there's
|
||||||
|
only one copy). This is ok as we restore it below. */
|
||||||
|
environ = (char**) env;
|
||||||
|
if ((flags & PEX_SEARCH) != 0)
|
||||||
|
{
|
||||||
|
execvp (executable, to_ptr32 (argv));
|
||||||
|
bad_fn = "execvp";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
execv (executable, to_ptr32 (argv));
|
||||||
|
bad_fn = "execv";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env)
|
/* Something failed, report an error. We don't use stdio
|
||||||
{
|
routines, because we might be here due to a vfork call. */
|
||||||
/* NOTE: In a standard vfork implementation this clobbers the
|
{
|
||||||
parent's copy of environ "too" (in reality there's only one copy).
|
ssize_t retval = 0;
|
||||||
This is ok as we restore it below. */
|
int err = errno;
|
||||||
environ = (char**) env;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & PEX_SEARCH) != 0)
|
#define writeerr(s) (retval |= write (STDERR_FILE_NO, s, strlen (s)))
|
||||||
{
|
writeerr (obj->pname);
|
||||||
execvp (executable, to_ptr32 (argv));
|
writeerr (": error trying to exec '");
|
||||||
pex_child_error (obj, executable, "execvp", errno);
|
writeerr (executable);
|
||||||
}
|
writeerr ("': ");
|
||||||
else
|
writeerr (bad_fn);
|
||||||
{
|
writeerr (": ");
|
||||||
execv (executable, to_ptr32 (argv));
|
writeerr (xstrerror (err));
|
||||||
pex_child_error (obj, executable, "execv", errno);
|
writeerr ("\n");
|
||||||
}
|
#undef writeerr
|
||||||
|
|
||||||
|
/* Exit with -2 if the error output failed, too. */
|
||||||
|
_exit (retval < 0 ? -2 : -1);
|
||||||
|
}
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
return (pid_t) -1;
|
return (pid_t) -1;
|
||||||
|
|
||||||
|
@ -689,32 +685,21 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
|
||||||
the child's copy of environ. */
|
the child's copy of environ. */
|
||||||
environ = save_environ;
|
environ = save_environ;
|
||||||
|
|
||||||
if (in != STDIN_FILE_NO)
|
if (!bad_fn && in != STDIN_FILE_NO)
|
||||||
|
if (close (in) < 0)
|
||||||
|
bad_fn = "close";
|
||||||
|
if (!bad_fn && out != STDOUT_FILE_NO)
|
||||||
|
if (close (out) < 0)
|
||||||
|
bad_fn = "close";
|
||||||
|
if (!bad_fn && errdes != STDERR_FILE_NO)
|
||||||
|
if (close (errdes) < 0)
|
||||||
|
bad_fn = "close";
|
||||||
|
|
||||||
|
if (bad_fn)
|
||||||
{
|
{
|
||||||
if (close (in) < 0)
|
*err = errno;
|
||||||
{
|
*errmsg = bad_fn;
|
||||||
*err = errno;
|
return (pid_t) -1;
|
||||||
*errmsg = "close";
|
|
||||||
return (pid_t) -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (out != STDOUT_FILE_NO)
|
|
||||||
{
|
|
||||||
if (close (out) < 0)
|
|
||||||
{
|
|
||||||
*err = errno;
|
|
||||||
*errmsg = "close";
|
|
||||||
return (pid_t) -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (errdes != STDERR_FILE_NO)
|
|
||||||
{
|
|
||||||
if (close (errdes) < 0)
|
|
||||||
{
|
|
||||||
*err = errno;
|
|
||||||
*errmsg = "close";
|
|
||||||
return (pid_t) -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pid;
|
return pid;
|
||||||
|
|
Loading…
Reference in New Issue