aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-03-04 22:17:58 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-03-04 22:17:58 +0000
commitb2c917476d2d2cc6ad2dd1ae3150b6a8dfca1ebe (patch)
treef482f40a2adaf0e034b3f295162434241a462be9
parentdb3f2240845fa9144cea4d14c8eba35c7bcc4d51 (diff)
parent6b384dece63de256f69de4b64fa12d77fcf386c8 (diff)
downloadbionic-simpleperf-release.tar.gz
Merge "Snap for 11526323 from 2c0e9a58ead53aff66f0978c51142d8331ffffb0 to simpleperf-release" into simpleperf-releasesimpleperf-release
-rw-r--r--libc/bionic/fork.cpp8
-rw-r--r--libc/include/android/crash_detail.h2
-rw-r--r--libc/include/bits/page_size.h2
-rw-r--r--libc/include/spawn.h2
-rw-r--r--libc/include/unistd.h33
-rw-r--r--libc/libc.map.txt1
-rw-r--r--tests/pthread_test.cpp41
-rw-r--r--tests/unistd_test.cpp16
8 files changed, 95 insertions, 10 deletions
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index d432c6db7..615e81f9f 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -50,11 +50,13 @@ int __clone_for_fork() {
return result;
}
+int _Fork() {
+ return __clone_for_fork();
+}
+
int fork() {
__bionic_atfork_run_prepare();
-
- int result = __clone_for_fork();
-
+ int result = _Fork();
if (result == 0) {
// Disable fdsan and fdtrack post-fork, so we don't falsely trigger on processes that
// fork, close all of their fds, and then exec.
diff --git a/libc/include/android/crash_detail.h b/libc/include/android/crash_detail.h
index 6744385ba..1889f9f41 100644
--- a/libc/include/android/crash_detail.h
+++ b/libc/include/android/crash_detail.h
@@ -34,8 +34,6 @@
*/
#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
diff --git a/libc/include/bits/page_size.h b/libc/include/bits/page_size.h
index ca434e568..df0cb7fcc 100644
--- a/libc/include/bits/page_size.h
+++ b/libc/include/bits/page_size.h
@@ -32,7 +32,7 @@
__BEGIN_DECLS
-#if !defined(__BIONIC_NO_PAGE_SIZE_MACRO)
+#if !defined(__BIONIC_NO_PAGE_SIZE_MACRO) || defined(__BIONIC_DEPRECATED_PAGE_SIZE_MACRO)
#define PAGE_SIZE 4096
#define PAGE_MASK (~(PAGE_SIZE - 1))
#endif
diff --git a/libc/include/spawn.h b/libc/include/spawn.h
index 6c34b98bc..3ce402fef 100644
--- a/libc/include/spawn.h
+++ b/libc/include/spawn.h
@@ -55,7 +55,7 @@ typedef struct __posix_spawn_file_actions* posix_spawn_file_actions_t;
int posix_spawn(pid_t* _Nullable __pid, const char* _Nonnull __path, const posix_spawn_file_actions_t _Nullable * _Nullable __actions, const posix_spawnattr_t _Nullable * _Nullable __attr, char* const _Nonnull __argv[_Nonnull], char* const _Nullable __env[_Nullable]) __INTRODUCED_IN(28);
int posix_spawnp(pid_t* _Nullable __pid, const char* _Nonnull __file, const posix_spawn_file_actions_t _Nullable * _Nullable __actions, const posix_spawnattr_t _Nullable * _Nullable __attr, char* const _Nonnull __argv[_Nonnull], char* const _Nullable __env[_Nullable]) __INTRODUCED_IN(28);
-int posix_spawnattr_init(posix_spawnattr_t _Nonnull * _Nonnull __attr) __INTRODUCED_IN(28);
+int posix_spawnattr_init(posix_spawnattr_t _Nullable * _Nonnull __attr) __INTRODUCED_IN(28);
int posix_spawnattr_destroy(posix_spawnattr_t _Nonnull * _Nonnull __attr) __INTRODUCED_IN(28);
int posix_spawnattr_setflags(posix_spawnattr_t _Nonnull * _Nonnull __attr, short __flags) __INTRODUCED_IN(28);
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index c8cceb21e..b94197eb0 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -78,8 +78,37 @@ extern char* _Nullable * _Nullable environ;
__noreturn void _exit(int __status);
-pid_t fork(void);
-pid_t vfork(void) __returns_twice;
+/**
+ * [fork(2)](http://man7.org/linux/man-pages/man2/fork.2.html) creates a new
+ * process. fork() runs any handlers set by pthread_atfork().
+ *
+ * Returns 0 in the child, the pid of the child in the parent,
+ * and returns -1 and sets `errno` on failure.
+ */
+pid_t fork(void);
+
+/**
+ * _Fork() creates a new process. _Fork() differs from fork() in that it does
+ * not run any handlers set by pthread_atfork().
+ *
+ * Returns 0 in the child, the pid of the child in the parent,
+ * and returns -1 and sets `errno` on failure.
+ *
+ * Available since API level 35.
+ */
+pid_t _Fork(void) __INTRODUCED_IN(35);
+
+/**
+ * [vfork(2)](http://man7.org/linux/man-pages/man2/vfork.2.html) creates a new
+ * process. vfork() differs from fork() in that it does not run any handlers
+ * set by pthread_atfork(), and the parent is suspended until the child calls
+ * exec() or exits.
+ *
+ * Returns 0 in the child, the pid of the child in the parent,
+ * and returns -1 and sets `errno` on failure.
+ */
+pid_t vfork(void) __returns_twice;
+
pid_t getpid(void);
pid_t gettid(void) __attribute_const__;
pid_t getpgid(pid_t __pid);
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 5e9763bef..2c8ec0796 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1592,6 +1592,7 @@ LIBC_V { # introduced=VanillaIceCream
android_crash_detail_replace_data;
epoll_pwait2;
epoll_pwait2_64;
+ _Fork;
localtime_rz;
mbsrtowcs_l;
mktime_z;
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 1a882beb5..2bf755b44 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -1423,10 +1423,11 @@ static int g_atfork_child_calls = 0;
static void AtForkChild1() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 1; }
static void AtForkChild2() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 2; }
-TEST(pthread, pthread_atfork_smoke) {
+TEST(pthread, pthread_atfork_smoke_fork) {
ASSERT_EQ(0, pthread_atfork(AtForkPrepare1, AtForkParent1, AtForkChild1));
ASSERT_EQ(0, pthread_atfork(AtForkPrepare2, AtForkParent2, AtForkChild2));
+ g_atfork_prepare_calls = g_atfork_parent_calls = g_atfork_child_calls = 0;
pid_t pid = fork();
ASSERT_NE(-1, pid) << strerror(errno);
@@ -1442,6 +1443,44 @@ TEST(pthread, pthread_atfork_smoke) {
AssertChildExited(pid, 0);
}
+TEST(pthread, pthread_atfork_smoke_vfork) {
+ ASSERT_EQ(0, pthread_atfork(AtForkPrepare1, AtForkParent1, AtForkChild1));
+ ASSERT_EQ(0, pthread_atfork(AtForkPrepare2, AtForkParent2, AtForkChild2));
+
+ g_atfork_prepare_calls = g_atfork_parent_calls = g_atfork_child_calls = 0;
+ pid_t pid = vfork();
+ ASSERT_NE(-1, pid) << strerror(errno);
+
+ // atfork handlers are not called.
+ if (pid == 0) {
+ ASSERT_EQ(0, g_atfork_child_calls);
+ _exit(0);
+ }
+ ASSERT_EQ(0, g_atfork_parent_calls);
+ ASSERT_EQ(0, g_atfork_prepare_calls);
+ AssertChildExited(pid, 0);
+}
+
+TEST(pthread, pthread_atfork_smoke__Fork) {
+#if defined(__BIONIC__)
+ ASSERT_EQ(0, pthread_atfork(AtForkPrepare1, AtForkParent1, AtForkChild1));
+ ASSERT_EQ(0, pthread_atfork(AtForkPrepare2, AtForkParent2, AtForkChild2));
+
+ g_atfork_prepare_calls = g_atfork_parent_calls = g_atfork_child_calls = 0;
+ pid_t pid = _Fork();
+ ASSERT_NE(-1, pid) << strerror(errno);
+
+ // atfork handlers are not called.
+ if (pid == 0) {
+ ASSERT_EQ(0, g_atfork_child_calls);
+ _exit(0);
+ }
+ ASSERT_EQ(0, g_atfork_parent_calls);
+ ASSERT_EQ(0, g_atfork_prepare_calls);
+ AssertChildExited(pid, 0);
+#endif
+}
+
TEST(pthread, pthread_attr_getscope) {
pthread_attr_t attr;
ASSERT_EQ(0, pthread_attr_init(&attr));
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 6c08972e6..78b55c18b 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -440,6 +440,22 @@ TEST(UNISTD_TEST, syncfs) {
TestSyncFunction(syncfs);
}
+TEST(UNISTD_TEST, _Fork) {
+#if defined(__BIONIC__)
+ pid_t rc = _Fork();
+ ASSERT_NE(-1, rc);
+ if (rc == 0) {
+ _exit(66);
+ }
+
+ int status;
+ pid_t wait_result = waitpid(rc, &status, 0);
+ ASSERT_EQ(wait_result, rc);
+ ASSERT_TRUE(WIFEXITED(status));
+ ASSERT_EQ(66, WEXITSTATUS(status));
+#endif
+}
+
TEST(UNISTD_TEST, vfork) {
#if defined(__BIONIC__)
pthread_internal_t* self = __get_thread();