From 085bb402c7b2c2f96624fb0523ff3f9686fe26d9 Mon Sep 17 00:00:00 2001
From: Tavian Barnes <tavianator@tavianator.com>
Date: Sat, 27 Jul 2024 19:10:16 -0400
Subject: xspawn: Use _Fork() if available

This completes the workaround for bfs_spawn() hanging on FreeBSD with
ASan enabled.

Link: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=280318
---
 build/flags.mk         | 1 +
 build/flags/bind-now.c | 8 ++++++++
 build/has/_Fork.c      | 8 ++++++++
 build/header.mk        | 1 +
 src/xspawn.c           | 4 ++++
 5 files changed, 22 insertions(+)
 create mode 100644 build/flags/bind-now.c
 create mode 100644 build/has/_Fork.c

diff --git a/build/flags.mk b/build/flags.mk
index 5c28c3f..0a62f32 100644
--- a/build/flags.mk
+++ b/build/flags.mk
@@ -105,6 +105,7 @@ include build/exports.mk
 
 # Conditionally-supported flags
 AUTO_FLAGS := \
+    gen/flags/bind-now.mk \
     gen/flags/deps.mk \
     gen/flags/missing-var-decls.mk
 
diff --git a/build/flags/bind-now.c b/build/flags/bind-now.c
new file mode 100644
index 0000000..08bb4f2
--- /dev/null
+++ b/build/flags/bind-now.c
@@ -0,0 +1,8 @@
+// Copyright © Tavian Barnes <tavianator@tavianator.com>
+// SPDX-License-Identifier: 0BSD
+
+/// _LDFLAGS += -Wl,-z,now
+
+int main(void) {
+	return 0;
+}
diff --git a/build/has/_Fork.c b/build/has/_Fork.c
new file mode 100644
index 0000000..4d7fbd3
--- /dev/null
+++ b/build/has/_Fork.c
@@ -0,0 +1,8 @@
+// Copyright © Tavian Barnes <tavianator@tavianator.com>
+// SPDX-License-Identifier: 0BSD
+
+#include <unistd.h>
+
+int main(void) {
+	return _Fork();
+}
diff --git a/build/header.mk b/build/header.mk
index afd04d0..a4f392e 100644
--- a/build/header.mk
+++ b/build/header.mk
@@ -13,6 +13,7 @@ include build/exports.mk
 # All header fragments we generate
 HEADERS := \
     gen/has/--st-birthtim.h \
+    gen/has/_Fork.h \
     gen/has/acl-get-entry.h \
     gen/has/acl-get-file.h \
     gen/has/acl-get-tag-type.h \
diff --git a/src/xspawn.c b/src/xspawn.c
index 68973ad..789f370 100644
--- a/src/xspawn.c
+++ b/src/xspawn.c
@@ -612,7 +612,11 @@ static pid_t bfs_fork_spawn(struct bfs_resolver *res, const struct bfs_spawn *ct
 		goto fail;
 	}
 
+#if BFS_HAS__FORK
+	pid_t pid = _Fork();
+#else
 	pid_t pid = fork();
+#endif
 	if (pid == 0) {
 		// Child
 		bfs_spawn_exec(res, ctx, argv, envp, pipefd);
-- 
cgit v1.2.3