Skip to content

Commit 7ab022f

Browse files
mrpippywaddlesplash
authored andcommitted
libiberty: Use posix_spawn in pex-unix when available.
Hi, This patch implements pex_unix_exec_child using posix_spawn when available. This should especially benefit recent macOS (where vfork just calls fork), but should have equivalent or faster performance on all platforms. In addition, the implementation is substantially simpler than the vfork+exec code path. Tested on x86_64-linux. v2: Fix error handling (previously the function would be run twice in case of error), and don't use a macro that changes control flow. v3: Match file style for error-handling blocks, don't close in/out/errdes on error, and check close() for errors. libiberty/ * configure.ac (AC_CHECK_HEADERS): Add spawn.h. (checkfuncs): Add posix_spawn, posix_spawnp. (AC_CHECK_FUNCS): Add posix_spawn, posix_spawnp. * aclocal.m4, configure, config.in: Rebuild. * pex-unix.c [HAVE_POSIX_SPAWN] (pex_unix_exec_child): New function.
1 parent 360fe2f commit 7ab022f

File tree

5 files changed

+189
-8
lines changed

5 files changed

+189
-8
lines changed

gcc/libiberty/aclocal.m4

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
1+
# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
22

3-
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
3+
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
44

55
# This file is free software; the Free Software Foundation
66
# gives unlimited permission to copy and/or distribute it,

gcc/libiberty/config.in

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@
198198
/* Define to 1 if you have the `pipe2' function. */
199199
#undef HAVE_PIPE2
200200

201+
/* Define to 1 if you have the `posix_spawn' function. */
202+
#undef HAVE_POSIX_SPAWN
203+
204+
/* Define to 1 if you have the `posix_spawnp' function. */
205+
#undef HAVE_POSIX_SPAWNP
206+
201207
/* Define to 1 if you have the <process.h> header file. */
202208
#undef HAVE_PROCESS_H
203209

@@ -249,6 +255,9 @@
249255
/* Define to 1 if you have the `spawnvpe' function. */
250256
#undef HAVE_SPAWNVPE
251257

258+
/* Define to 1 if you have the <spawn.h> header file. */
259+
#undef HAVE_SPAWN_H
260+
252261
/* Define to 1 if you have the <stdint.h> header file. */
253262
#undef HAVE_STDINT_H
254263

gcc/libiberty/configure

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5517,7 +5517,7 @@ host_makefile_frag=${frag}
55175517
# It's OK to check for header files. Although the compiler may not be
55185518
# able to link anything, it had better be able to at least compile
55195519
# something.
5520-
for ac_header in sys/file.h sys/param.h limits.h stdlib.h malloc.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 sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h stdint.h stdio_ext.h process.h sys/prctl.h
5520+
for ac_header in sys/file.h sys/param.h limits.h stdlib.h malloc.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 sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h stdint.h stdio_ext.h process.h sys/prctl.h spawn.h
55215521
do :
55225522
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
55235523
ac_fn_c_check_header_preproc "$LINENO" "$ac_header" "$as_ac_Header"
@@ -6026,7 +6026,8 @@ funcs="$funcs setproctitle"
60266026
vars="sys_errlist sys_nerr sys_siglist"
60276027
60286028
checkfuncs="__fsetlocking canonicalize_file_name dup3 getrlimit getrusage \
6029-
getsysinfo gettimeofday on_exit pipe2 psignal pstat_getdynamic pstat_getstatic \
6029+
getsysinfo gettimeofday on_exit pipe2 posix_spawn posix_spawnp psignal \
6030+
pstat_getdynamic pstat_getstatic \
60306031
realpath setrlimit spawnve spawnvpe strerror strsignal sysconf sysctl \
60316032
sysmp table times wait3 wait4"
60326033
@@ -6049,7 +6050,8 @@ if test "x" = "y"; then
60496050
index insque \
60506051
memchr memcmp memcpy memmem memmove memset mkstemps \
60516052
on_exit \
6052-
pipe2 psignal pstat_getdynamic pstat_getstatic putenv \
6053+
pipe2 posix_spawn posix_spawnp psignal \
6054+
pstat_getdynamic pstat_getstatic putenv \
60536055
random realpath rename rindex \
60546056
sbrk setenv setproctitle setrlimit sigsetmask snprintf spawnve spawnvpe \
60556057
stpcpy stpncpy strcasecmp strchr strdup \

gcc/libiberty/configure.ac

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ AC_SUBST_FILE(host_makefile_frag)
277277
# It's OK to check for header files. Although the compiler may not be
278278
# able to link anything, it had better be able to at least compile
279279
# something.
280-
AC_CHECK_HEADERS(sys/file.h sys/param.h limits.h stdlib.h malloc.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 sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h stdint.h stdio_ext.h process.h sys/prctl.h)
280+
AC_CHECK_HEADERS(sys/file.h sys/param.h limits.h stdlib.h malloc.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 sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h stdint.h stdio_ext.h process.h sys/prctl.h spawn.h)
281281
AC_HEADER_SYS_WAIT
282282
AC_HEADER_TIME
283283

@@ -400,7 +400,8 @@ funcs="$funcs setproctitle"
400400
vars="sys_errlist sys_nerr sys_siglist"
401401

402402
checkfuncs="__fsetlocking canonicalize_file_name dup3 getrlimit getrusage \
403-
getsysinfo gettimeofday on_exit pipe2 psignal pstat_getdynamic pstat_getstatic \
403+
getsysinfo gettimeofday on_exit pipe2 posix_spawn posix_spawnp psignal \
404+
pstat_getdynamic pstat_getstatic \
404405
realpath setrlimit spawnve spawnvpe strerror strsignal sysconf sysctl \
405406
sysmp table times wait3 wait4"
406407

@@ -423,7 +424,8 @@ if test "x" = "y"; then
423424
index insque \
424425
memchr memcmp memcpy memmem memmove memset mkstemps \
425426
on_exit \
426-
pipe2 psignal pstat_getdynamic pstat_getstatic putenv \
427+
pipe2 posix_spawn posix_spawnp psignal \
428+
pstat_getdynamic pstat_getstatic putenv \
427429
random realpath rename rindex \
428430
sbrk setenv setproctitle setrlimit sigsetmask snprintf spawnve spawnvpe \
429431
stpcpy stpncpy strcasecmp strchr strdup \

gcc/libiberty/pex-unix.c

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ extern int errno;
5858
#ifdef HAVE_PROCESS_H
5959
#include <process.h>
6060
#endif
61+
#ifdef HAVE_SPAWN_H
62+
#include <spawn.h>
63+
#endif
6164

6265
#ifdef vfork /* Autoconf may define this to fork for us. */
6366
# define VFORK_STRING "fork"
@@ -559,6 +562,171 @@ pex_unix_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED,
559562
return (pid_t) -1;
560563
}
561564

565+
#elif defined(HAVE_POSIX_SPAWN) && defined(HAVE_POSIX_SPAWNP)
566+
/* Implementation of pex->exec_child using posix_spawn. */
567+
568+
static pid_t
569+
pex_unix_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED,
570+
int flags, const char *executable,
571+
char * const * argv, char * const * env,
572+
int in, int out, int errdes,
573+
int toclose, const char **errmsg, int *err)
574+
{
575+
int ret;
576+
pid_t pid = -1;
577+
posix_spawnattr_t attr;
578+
posix_spawn_file_actions_t actions;
579+
int attr_initialized = 0, actions_initialized = 0;
580+
581+
*err = 0;
582+
583+
ret = posix_spawnattr_init (&attr);
584+
if (ret)
585+
{
586+
*err = ret;
587+
*errmsg = "posix_spawnattr_init";
588+
goto exit;
589+
}
590+
attr_initialized = 1;
591+
592+
/* Use vfork() on glibc <=2.24. */
593+
#ifdef POSIX_SPAWN_USEVFORK
594+
ret = posix_spawnattr_setflags (&attr, POSIX_SPAWN_USEVFORK);
595+
if (ret)
596+
{
597+
*err = ret;
598+
*errmsg = "posix_spawnattr_setflags";
599+
goto exit;
600+
}
601+
#endif
602+
603+
ret = posix_spawn_file_actions_init (&actions);
604+
if (ret)
605+
{
606+
*err = ret;
607+
*errmsg = "posix_spawn_file_actions_init";
608+
goto exit;
609+
}
610+
actions_initialized = 1;
611+
612+
if (in != STDIN_FILE_NO)
613+
{
614+
ret = posix_spawn_file_actions_adddup2 (&actions, in, STDIN_FILE_NO);
615+
if (ret)
616+
{
617+
*err = ret;
618+
*errmsg = "posix_spawn_file_actions_adddup2";
619+
goto exit;
620+
}
621+
622+
ret = posix_spawn_file_actions_addclose (&actions, in);
623+
if (ret)
624+
{
625+
*err = ret;
626+
*errmsg = "posix_spawn_file_actions_addclose";
627+
goto exit;
628+
}
629+
}
630+
631+
if (out != STDOUT_FILE_NO)
632+
{
633+
ret = posix_spawn_file_actions_adddup2 (&actions, out, STDOUT_FILE_NO);
634+
if (ret)
635+
{
636+
*err = ret;
637+
*errmsg = "posix_spawn_file_actions_adddup2";
638+
goto exit;
639+
}
640+
641+
ret = posix_spawn_file_actions_addclose (&actions, out);
642+
if (ret)
643+
{
644+
*err = ret;
645+
*errmsg = "posix_spawn_file_actions_addclose";
646+
goto exit;
647+
}
648+
}
649+
650+
if (errdes != STDERR_FILE_NO)
651+
{
652+
ret = posix_spawn_file_actions_adddup2 (&actions, errdes, STDERR_FILE_NO);
653+
if (ret)
654+
{
655+
*err = ret;
656+
*errmsg = "posix_spawn_file_actions_adddup2";
657+
goto exit;
658+
}
659+
660+
ret = posix_spawn_file_actions_addclose (&actions, errdes);
661+
if (ret)
662+
{
663+
*err = ret;
664+
*errmsg = "posix_spawn_file_actions_addclose";
665+
goto exit;
666+
}
667+
}
668+
669+
if (toclose >= 0)
670+
{
671+
ret = posix_spawn_file_actions_addclose (&actions, toclose);
672+
if (ret)
673+
{
674+
*err = ret;
675+
*errmsg = "posix_spawn_file_actions_addclose";
676+
goto exit;
677+
}
678+
}
679+
680+
if ((flags & PEX_STDERR_TO_STDOUT) != 0)
681+
{
682+
ret = posix_spawn_file_actions_adddup2 (&actions, STDOUT_FILE_NO, STDERR_FILE_NO);
683+
if (ret)
684+
{
685+
*err = ret;
686+
*errmsg = "posix_spawn_file_actions_adddup2";
687+
goto exit;
688+
}
689+
}
690+
691+
if ((flags & PEX_SEARCH) != 0)
692+
{
693+
ret = posix_spawnp (&pid, executable, &actions, &attr, argv, env ? env : environ);
694+
if (ret)
695+
{
696+
*err = ret;
697+
*errmsg = "posix_spawnp";
698+
goto exit;
699+
}
700+
}
701+
else
702+
{
703+
ret = posix_spawn (&pid, executable, &actions, &attr, argv, env ? env : environ);
704+
if (ret)
705+
{
706+
*err = ret;
707+
*errmsg = "posix_spawn";
708+
goto exit;
709+
}
710+
}
711+
712+
exit:
713+
if (actions_initialized)
714+
posix_spawn_file_actions_destroy (&actions);
715+
if (attr_initialized)
716+
posix_spawnattr_destroy (&attr);
717+
718+
if (!*err && in != STDIN_FILE_NO)
719+
if (close (in))
720+
*errmsg = "close", *err = errno, pid = -1;
721+
if (!*err && out != STDOUT_FILE_NO)
722+
if (close (out))
723+
*errmsg = "close", *err = errno, pid = -1;
724+
if (!*err && errdes != STDERR_FILE_NO)
725+
if (close (errdes))
726+
*errmsg = "close", *err = errno, pid = -1;
727+
728+
return pid;
729+
}
562730
#else
563731
/* Implementation of pex->exec_child using standard vfork + exec. */
564732

0 commit comments

Comments
 (0)