From patchwork Wed Oct 4 18:28:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brendan Shanks X-Patchwork-Id: 148448 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:254a:b0:403:3b70:6f57 with SMTP id hf10csp327459vqb; Wed, 4 Oct 2023 11:30:50 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFmgkr6hsyAe7At98PqB62c6Qs34f9VwFSD8uLsamd9ZCfkUlEa5SZk/xFFHy5xZ9tBz7nA X-Received: by 2002:a17:907:270b:b0:9b2:c0ea:af85 with SMTP id w11-20020a170907270b00b009b2c0eaaf85mr2948416ejk.14.1696444250242; Wed, 04 Oct 2023 11:30:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696444250; cv=none; d=google.com; s=arc-20160816; b=Jbx13YxCZnrSIRXZam7rS8CxwJwMd18uNrb/3a0lNZJFK7WqKZi53VeEIaiOOdgu9q j0K8L4SzDcdsyPhkOFsF4sVMwbPJLf0ObdPN8V8Ip6dJJFwwuU9HiUC/e9mPISUCrROi ViRbPKe5/MnW6AyVHPVgxHbwkofBEYqmrafvuCiHiwEZ2AAxXnGsQnK0NDkcMiH7leQm T/ecRtaJgjhum30lX8L04Fq0OrGceST5S3iKcKfDHIyhXGRRy7ZEXx0Aa99L0Qk2uPqP nB6ah1cuvPICHBnBtEkX4tmM9vPVW4YNfTlO2DqcXREXhYKujSGUIaOSoUvD2SbDqOBg NncA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature :dmarc-filter:delivered-to; bh=4Zq1Un5bRY7j9G9re2qh5Rc+fs4Z6cPjxPjAAlXIS6w=; fh=QiogErZPgyLKS8sr17tmBJKC6nJZFHjteHo56ry6e5g=; b=MFP19KAOoN7u2pY4lYGP4giQ8bzwImVlo9XFF3Hld6oMtJ+00m4qSmKW7NBkViqcPy w1f70gDWRCCbCf+7jnz6IQjhSoZPsS8FlbWhwvI+QsHwA84E126Mk0abkXgjk8gaDmYn IWTSCsLPPHy2vizUq2u1QesvUefndlffKyGPsPNGHOF4s+Ad4V7s8G23g8BjhpLiFUYv sShaUEPfsv+pyM04H0YWLl3/TSf79jy+JppJ1ahrycoZR6xyOL4pwQ4YiM1YuBumxUlX sGty0LT2BR8MoyLcdM64Vk0x3/SjM3OdjX8UzVOPxE0PwoD/2C8NIz+1s62bA0sg3kS9 2DMw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeweavers.com header.s=s1 header.b=nyaXgcSo; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=codeweavers.com Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id jt18-20020a170906ca1200b0099cc36c6bdcsi1976015ejb.151.2023.10.04.11.30.49 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Oct 2023 11:30:50 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@codeweavers.com header.s=s1 header.b=nyaXgcSo; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=codeweavers.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 92A2D385C6FF for ; Wed, 4 Oct 2023 18:30:45 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail.codeweavers.com (mail.codeweavers.com [4.36.192.163]) by sourceware.org (Postfix) with ESMTPS id C23663857711 for ; Wed, 4 Oct 2023 18:30:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C23663857711 Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=codeweavers.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=codeweavers.com DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=codeweavers.com; s=s1; h=Message-ID:Date:Subject:Cc:To:From:Sender; bh=4Zq1Un5bRY7j9G9re2qh5Rc+fs4Z6cPjxPjAAlXIS6w=; b=nyaXgcSoPnoqpe7/vECTS3Zhpf UnLNhI0XU9Q+nYkp/imNLc4xR7Zw9p9deGUlwTlTdP4+o/I3KLLNmr0msGpV5wmyGdZkMV50ruwbs E7DAa+0pnu/jeZ5AUmybV+f4dRWejbtxb4tA8ZpnV/g3kmA/Tt1mgJBiPYQPlHqZHrra8NKoJTGaT oxpo//540JOg7rHnZoEBaBytFP0qwqlzw422teVgUIUdPHzoL5YaEpL47Fx7YG7YKau+d1Pck8b8j cj2DeLNhf6w8HhW1gAdCKpHzHc+fj8tj6yXMtLR5oFdpRWRc57Ai3BZZWBvsNMR/cq4/VqMPiUv5r byZ61PkQ==; Received: from ip72-203-125-151.oc.oc.cox.net ([72.203.125.151] helo=zen.bslabs.net) by mail.codeweavers.com with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1qo6dX-003WqH-9T; Wed, 04 Oct 2023 13:30:19 -0500 From: Brendan Shanks To: gcc-patches@gcc.gnu.org Cc: Brendan Shanks Subject: [PATCH v3] libiberty: Use posix_spawn in pex-unix when available. Date: Wed, 4 Oct 2023 11:28:28 -0700 Message-ID: <20231004183004.29161-1-bshanks@codeweavers.com> X-Mailer: git-send-email 2.41.0 MIME-Version: 1.0 X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778850726284072108 X-GMAIL-MSGID: 1778850726284072108 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. * configure, config.in: Rebuild. * pex-unix.c [HAVE_POSIX_SPAWN] (pex_unix_exec_child): New function. Signed-off-by: Brendan Shanks --- libiberty/configure.ac | 8 +- libiberty/pex-unix.c | 168 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 3 deletions(-) diff --git a/libiberty/configure.ac b/libiberty/configure.ac index 0748c592704..2488b031bc8 100644 --- a/libiberty/configure.ac +++ b/libiberty/configure.ac @@ -289,7 +289,7 @@ AC_SUBST_FILE(host_makefile_frag) # 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 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) +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) AC_HEADER_SYS_WAIT AC_HEADER_TIME @@ -412,7 +412,8 @@ funcs="$funcs setproctitle" vars="sys_errlist sys_nerr sys_siglist" checkfuncs="__fsetlocking canonicalize_file_name dup3 getrlimit getrusage \ - getsysinfo gettimeofday on_exit pipe2 psignal pstat_getdynamic pstat_getstatic \ + getsysinfo gettimeofday on_exit pipe2 posix_spawn posix_spawnp psignal \ + pstat_getdynamic pstat_getstatic \ realpath setrlimit spawnve spawnvpe strerror strsignal sysconf sysctl \ sysmp table times wait3 wait4" @@ -435,7 +436,8 @@ if test "x" = "y"; then index insque \ memchr memcmp memcpy memmem memmove memset mkstemps \ on_exit \ - pipe2 psignal pstat_getdynamic pstat_getstatic putenv \ + pipe2 posix_spawn posix_spawnp psignal \ + pstat_getdynamic pstat_getstatic putenv \ random realpath rename rindex \ sbrk setenv setproctitle setrlimit sigsetmask snprintf spawnve spawnvpe \ stpcpy stpncpy strcasecmp strchr strdup \ diff --git a/libiberty/pex-unix.c b/libiberty/pex-unix.c index 33b5bce31c2..336799d1125 100644 --- a/libiberty/pex-unix.c +++ b/libiberty/pex-unix.c @@ -58,6 +58,9 @@ extern int errno; #ifdef HAVE_PROCESS_H #include #endif +#ifdef HAVE_SPAWN_H +#include +#endif #ifdef vfork /* Autoconf may define this to fork for us. */ # define VFORK_STRING "fork" @@ -559,6 +562,171 @@ pex_unix_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, return (pid_t) -1; } +#elif defined(HAVE_POSIX_SPAWN) && defined(HAVE_POSIX_SPAWNP) +/* Implementation of pex->exec_child using posix_spawn. */ + +static pid_t +pex_unix_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, + int flags, const char *executable, + char * const * argv, char * const * env, + int in, int out, int errdes, + int toclose, const char **errmsg, int *err) +{ + int ret; + pid_t pid = -1; + posix_spawnattr_t attr; + posix_spawn_file_actions_t actions; + int attr_initialized = 0, actions_initialized = 0; + + *err = 0; + + ret = posix_spawnattr_init (&attr); + if (ret) + { + *err = ret; + *errmsg = "posix_spawnattr_init"; + goto exit; + } + attr_initialized = 1; + + /* Use vfork() on glibc <=2.24. */ +#ifdef POSIX_SPAWN_USEVFORK + ret = posix_spawnattr_setflags (&attr, POSIX_SPAWN_USEVFORK); + if (ret) + { + *err = ret; + *errmsg = "posix_spawnattr_setflags"; + goto exit; + } +#endif + + ret = posix_spawn_file_actions_init (&actions); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_init"; + goto exit; + } + actions_initialized = 1; + + if (in != STDIN_FILE_NO) + { + ret = posix_spawn_file_actions_adddup2 (&actions, in, STDIN_FILE_NO); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_adddup2"; + goto exit; + } + + ret = posix_spawn_file_actions_addclose (&actions, in); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_addclose"; + goto exit; + } + } + + if (out != STDOUT_FILE_NO) + { + ret = posix_spawn_file_actions_adddup2 (&actions, out, STDOUT_FILE_NO); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_adddup2"; + goto exit; + } + + ret = posix_spawn_file_actions_addclose (&actions, out); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_addclose"; + goto exit; + } + } + + if (errdes != STDERR_FILE_NO) + { + ret = posix_spawn_file_actions_adddup2 (&actions, errdes, STDERR_FILE_NO); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_adddup2"; + goto exit; + } + + ret = posix_spawn_file_actions_addclose (&actions, errdes); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_addclose"; + goto exit; + } + } + + if (toclose >= 0) + { + ret = posix_spawn_file_actions_addclose (&actions, toclose); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_addclose"; + goto exit; + } + } + + if ((flags & PEX_STDERR_TO_STDOUT) != 0) + { + ret = posix_spawn_file_actions_adddup2 (&actions, STDOUT_FILE_NO, STDERR_FILE_NO); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_adddup2"; + goto exit; + } + } + + if ((flags & PEX_SEARCH) != 0) + { + ret = posix_spawnp (&pid, executable, &actions, &attr, argv, env ? env : environ); + if (ret) + { + *err = ret; + *errmsg = "posix_spawnp"; + goto exit; + } + } + else + { + ret = posix_spawn (&pid, executable, &actions, &attr, argv, env ? env : environ); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn"; + goto exit; + } + } + +exit: + if (actions_initialized) + posix_spawn_file_actions_destroy (&actions); + if (attr_initialized) + posix_spawnattr_destroy (&attr); + + if (!*err && in != STDIN_FILE_NO) + if (close (in)) + *errmsg = "close", *err = errno, pid = -1; + if (!*err && out != STDOUT_FILE_NO) + if (close (out)) + *errmsg = "close", *err = errno, pid = -1; + if (!*err && errdes != STDERR_FILE_NO) + if (close (errdes)) + *errmsg = "close", *err = errno, pid = -1; + + return pid; +} #else /* Implementation of pex->exec_child using standard vfork + exec. */