aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2015-07-03 15:17:25 -0500
committerRob Landley <rob@landley.net>2015-07-03 15:17:25 -0500
commit9933273c5b7b6e0471d9195e8c2facb795b795ae (patch)
tree87d5e8a404ec360a69b80648f622d2bfc5bfecd0
parent82d8d7cb7eacabd1a498c001dd5618a1302f854b (diff)
downloadtoybox-9933273c5b7b6e0471d9195e8c2facb795b795ae.tar.gz
Probe for fork() instead of relying on a distro-specific #define.
-rw-r--r--lib/portability.c15
-rwxr-xr-xscripts/genconfig.sh6
2 files changed, 20 insertions, 1 deletions
diff --git a/lib/portability.c b/lib/portability.c
index 4da49dd6..78e500b1 100644
--- a/lib/portability.c
+++ b/lib/portability.c
@@ -6,7 +6,20 @@
#include "toys.h"
-#if !defined(__uClinux__)
+// We can't fork() on nommu systems, and vfork() requires an exec() or exit()
+// before resuming the parent (because they share a heap until then). And no,
+// we can't implement our own clone() call that does the equivalent of fork()
+// because nommu heaps use physical addresses so if we copy the heap all our
+// pointers are wrong. (You need an mmu in order to map two heaps to the same
+// address range without interfering with each other.) In the absence of
+// a portable way to tell malloc() to start a new heap without freeing the old
+// one, you pretty much need the exec().)
+
+// So we exec ourselves (via /proc/self/exe, if anybody knows a way to
+// re-exec self without depending on the filesystem, I'm all ears),
+// and use the arguments to signal reentry.
+
+#if CFG_TOYBOX_FORK
pid_t xfork(void)
{
pid_t pid = fork();
diff --git a/scripts/genconfig.sh b/scripts/genconfig.sh
index 313c7c70..031e97e0 100755
--- a/scripts/genconfig.sh
+++ b/scripts/genconfig.sh
@@ -83,6 +83,12 @@ EOF
#error nope
#endif
EOF
+
+ # nommu support
+ probesymbol TOYBOX_FORK << EOF
+ #include <unistd.h>
+ int main(int argc, char *argv[]) { return fork(); }
+EOF
}
genconfig()