diff options
author | jperkin <jperkin@pkgsrc.org> | 2021-11-15 12:48:23 +0000 |
---|---|---|
committer | jperkin <jperkin@pkgsrc.org> | 2021-11-15 12:48:23 +0000 |
commit | 16458371ab767f61bd401b586cd168a852128567 (patch) | |
tree | c0e3d6d4019505f0ee80642a9b24d240ee00e618 /pkgtools/pkg_install | |
parent | 1e8a31d8b67c51e004b75bd5a711ea4011beadee (diff) | |
download | pkgsrc-16458371ab767f61bd401b586cd168a852128567.tar.gz |
pkg_install: Switch to posix_spawn() on newer macOS.
vfork() no longer works on Monterey and causes serious intermittent issues
when upgrading pkg_install. Forking the INSTALL and DEINSTALL scripts can
sometimes fail, due to the underlying pkg_add/pkg_delete binaries having
been changed or removed, leaving the system broken with no package tools.
The manual page suggests using posix_spawn() instead and that appears to
work correctly. The code has been laid out so that it's easy enough to
switch other platforms to posix_spawn() too if required, or for improved
performance, and has been verified to work successfully on SmartOS.
Bump pkg_install version to 20211115.
Diffstat (limited to 'pkgtools/pkg_install')
-rw-r--r-- | pkgtools/pkg_install/files/lib/fexec.c | 67 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/lib/version.h | 4 |
2 files changed, 67 insertions, 4 deletions
diff --git a/pkgtools/pkg_install/files/lib/fexec.c b/pkgtools/pkg_install/files/lib/fexec.c index 540159863aa..6bf313367de 100644 --- a/pkgtools/pkg_install/files/lib/fexec.c +++ b/pkgtools/pkg_install/files/lib/fexec.c @@ -1,4 +1,4 @@ -/* $NetBSD: fexec.c,v 1.12 2009/08/02 17:56:45 joerg Exp $ */ +/* $NetBSD: fexec.c,v 1.13 2021/11/15 12:48:23 jperkin Exp $ */ /*- * Copyright (c) 2003 The NetBSD Foundation, Inc. @@ -37,6 +37,12 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif +#if HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#if HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif #if HAVE_SYS_WAIT_H #include <sys/wait.h> #endif @@ -47,6 +53,9 @@ #if HAVE_ERRNO_H #include <errno.h> #endif +#if HAVE_FCNTL_H +#include <fcntl.h> +#endif #if HAVE_STDARG_H #include <stdarg.h> #endif @@ -59,7 +68,33 @@ #include "lib.h" -__RCSID("$NetBSD: fexec.c,v 1.12 2009/08/02 17:56:45 joerg Exp $"); +/* + * Newer macOS releases are not able to correctly handle vfork() when the + * underlying file is changed or removed, as is the case when upgrading + * pkg_install itself. The manual pages suggest using posix_spawn() + * instead, which seems to work ok. + */ +#if defined(__APPLE__) && \ + ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1050) +#define FEXEC_USE_POSIX_SPAWN 1 +#else +#define FEXEC_USE_POSIX_SPAWN 0 +#endif + +#if FEXEC_USE_POSIX_SPAWN +#include <spawn.h> +extern char **environ; + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +#ifndef O_DIRECTORY +#define O_DIRECTORY 0 +#endif +#endif + +__RCSID("$NetBSD: fexec.c,v 1.13 2021/11/15 12:48:23 jperkin Exp $"); static int vfcexec(const char *, int, const char *, va_list); @@ -67,6 +102,8 @@ static int vfcexec(const char *, int, const char *, va_list); * fork, then change current working directory to path and * execute the command and arguments in the argv array. * wait for the command to finish, then return the exit status. + * + * macOS uses posix_spawn() instead due to reasons explained above. */ int pfcexec(const char *path, const char *file, const char **argv) @@ -74,6 +111,31 @@ pfcexec(const char *path, const char *file, const char **argv) pid_t child; int status; +#if FEXEC_USE_POSIX_SPAWN + int prevcwd; + + if ((prevcwd = open(".", O_RDONLY|O_CLOEXEC|O_DIRECTORY)) < 0) { + warn("open prevcwd failed"); + return -1; + } + + if ((path != NULL) && (chdir(path) < 0)) { + warn("chdir %s failed", path); + return -1; + } + + if (posix_spawn(&child, file, NULL, NULL, (char **)argv, environ) < 0) { + warn("posix_spawn failed"); + return -1; + } + + if (fchdir(prevcwd) < 0) { + warn("fchdir prevcwd failed"); + return -1; + } + + (void)close(prevcwd); +#else child = vfork(); switch (child) { case 0: @@ -86,6 +148,7 @@ pfcexec(const char *path, const char *file, const char **argv) case -1: return -1; } +#endif while (waitpid(child, &status, 0) < 0) { if (errno != EINTR) diff --git a/pkgtools/pkg_install/files/lib/version.h b/pkgtools/pkg_install/files/lib/version.h index 574922c89db..9bd3ab0a0de 100644 --- a/pkgtools/pkg_install/files/lib/version.h +++ b/pkgtools/pkg_install/files/lib/version.h @@ -1,4 +1,4 @@ -/* $NetBSD: version.h,v 1.188 2021/10/21 13:05:25 jperkin Exp $ */ +/* $NetBSD: version.h,v 1.189 2021/11/15 12:48:23 jperkin Exp $ */ /* * Copyright (c) 2001 Thomas Klausner. All rights reserved. @@ -27,6 +27,6 @@ #ifndef _INST_LIB_VERSION_H_ #define _INST_LIB_VERSION_H_ -#define PKGTOOLS_VERSION 20211021 +#define PKGTOOLS_VERSION 20211115 #endif /* _INST_LIB_VERSION_H_ */ |