Skip to content

Instantly share code, notes, and snippets.

@jperkin
Last active November 3, 2021 16:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jperkin/ae32d3464e3a2d261945608f80d8b8c1 to your computer and use it in GitHub Desktop.
Save jperkin/ae32d3464e3a2d261945608f80d8b8c1 to your computer and use it in GitHub Desktop.
diff --git a/pkgtools/pkg_install/files/lib/fexec.c b/pkgtools/pkg_install/files/lib/fexec.c
index 540159863aa..592bd51f886 100644
--- a/pkgtools/pkg_install/files/lib/fexec.c
+++ b/pkgtools/pkg_install/files/lib/fexec.c
@@ -59,6 +59,16 @@
#include "lib.h"
+/*
+ * Newer macOS releases are not able to correctly handle vfork() when the
+ * underlying file is changed or removed, but posix_spawn() seems to still
+ * work ok.
+ */
+#ifdef __APPLE__
+#include <spawn.h>
+extern char **environ;
+#endif
+
__RCSID("$NetBSD: fexec.c,v 1.12 2009/08/02 17:56:45 joerg Exp $");
static int vfcexec(const char *, int, const char *, va_list);
@@ -67,6 +77,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 +86,29 @@ pfcexec(const char *path, const char *file, const char **argv)
pid_t child;
int status;
+#ifdef __APPLE__
+ char oldcwd[PATH_MAX];
+
+ if (getcwd(oldcwd, sizeof(oldcwd)) == NULL) {
+ warn("getcwd failed");
+ return -1;
+ }
+
+ if ((path != NULL) && (chdir(path) < 0)) {
+ warn("chdir failed");
+ return -1;
+ }
+
+ if (posix_spawn(&child, file, NULL, NULL, argv, environ) < 0) {
+ warn("posix_spawn failed");
+ return -1;
+ }
+
+ if (chdir(oldcwd) < 0) {
+ warn("chdir failed");
+ return -1;
+ }
+#else
child = vfork();
switch (child) {
case 0:
@@ -86,6 +121,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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment