summaryrefslogtreecommitdiff
path: root/pkgtools/pkg_install
diff options
context:
space:
mode:
authorjperkin <jperkin@pkgsrc.org>2021-11-15 12:48:23 +0000
committerjperkin <jperkin@pkgsrc.org>2021-11-15 12:48:23 +0000
commit16458371ab767f61bd401b586cd168a852128567 (patch)
treec0e3d6d4019505f0ee80642a9b24d240ee00e618 /pkgtools/pkg_install
parent1e8a31d8b67c51e004b75bd5a711ea4011beadee (diff)
downloadpkgsrc-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.c67
-rw-r--r--pkgtools/pkg_install/files/lib/version.h4
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_ */