Generalize the clone function slightly.
* Allow clone where both the child function and stack are null. It's
obviously wrong to ask to call a function without a stack, but it's not
necessarily wrong to supply no stack if you're also not supplying a
function.
* Reimplement fork in terms of the clone function, rather than using the
clone system call directly.
This is intended as a step towards enabling use of pid namespaces.
Change-Id: I03c89bd1dc540d8b4ed1c8fdf6644290744b9e91
diff --git a/libc/bionic/clone.cpp b/libc/bionic/clone.cpp
index af63977..8281ac8 100644
--- a/libc/bionic/clone.cpp
+++ b/libc/bionic/clone.cpp
@@ -47,7 +47,7 @@
void* new_tls = NULL;
int* child_tid = NULL;
- if (!child_stack) {
+ if (fn != nullptr && child_stack == nullptr) {
errno = EINVAL;
return -1;
}
@@ -76,7 +76,16 @@
pid_t parent_pid = self->invalidate_cached_pid();
// Actually do the clone.
- int clone_result = __bionic_clone(flags, child_stack, parent_tid, new_tls, child_tid, fn, arg);
+ int clone_result;
+ if (fn != nullptr) {
+ clone_result = __bionic_clone(flags, child_stack, parent_tid, new_tls, child_tid, fn, arg);
+ } else {
+#if defined(__x86_64__) // sys_clone's last two arguments are flipped on x86-64.
+ clone_result = syscall(__NR_clone, flags, child_stack, parent_tid, child_tid, new_tls);
+#else
+ clone_result = syscall(__NR_clone, flags, child_stack, parent_tid, new_tls, child_tid);
+#endif
+ }
// We're the parent, so put our known pid back in place.
// We leave the child without a cached pid, but: