// Test addclose and adddup2 by redirecting output to the pipe created above.
ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[0]));
ASSERT_EQ(0, posix_spawn_file_actions_adddup2(&fa, fds[1], 1));
ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[1])); // Check that close(2) failures are ignored by closing the same fd again.
ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[1])); // Open a file directly, to test addopen.
ASSERT_EQ(0, posix_spawn_file_actions_addopen(&fa, 56, "/proc/version", O_RDONLY, 0)); // Test addfchdir by opening the same file a second way...
ASSERT_EQ(0, posix_spawn_file_actions_addopen(&fa, 57, "/proc", O_PATH, 0));
ASSERT_EQ(0, posix_spawn_file_actions_addfchdir(&fa, 57));
ASSERT_EQ(0, posix_spawn_file_actions_addopen(&fa, 58, "version", O_RDONLY, 0)); // Test addchdir by opening the same file a third way...
ASSERT_EQ(0, posix_spawn_file_actions_addchdir(&fa, "/"));
ASSERT_EQ(0, posix_spawn_file_actions_addopen(&fa, 59, "proc/version", O_RDONLY, 0));
// We'll know the dup2 worked if we see any ls(1) output in our pipe. // The opens we can check manually (and they implicitly check the chdirs)... bool open_to_fd_56_worked = false; bool open_to_fd_58_worked = false; bool open_to_fd_59_worked = false; for (constauto& line : android::base::Split(content, "\n")) { if (line.find(" 56 -> /proc/version") != std::string::npos) open_to_fd_56_worked = true; if (line.find(" 58 -> /proc/version") != std::string::npos) open_to_fd_58_worked = true; if (line.find(" 59 -> /proc/version") != std::string::npos) open_to_fd_59_worked = true;
}
ASSERT_TRUE(open_to_fd_56_worked) << content;
ASSERT_TRUE(open_to_fd_58_worked) << content;
ASSERT_TRUE(open_to_fd_59_worked) << content; #else
GTEST_SKIP() << "our old glibc doesn't have the chdirs; newer versions and musl do."; #endif
}
staticvoid CatFileToString(posix_spawnattr_t* sa, constchar* path, std::string* content) { int fds[2];
ASSERT_NE(-1, pipe(fds));
ProcStat ps = {};
GetChildStat(&sa, &ps);
ASSERT_NE(parent_pgrp, ps.pgrp); // Setting pgid 0 means "the same as the caller's pid".
ASSERT_EQ(ps.pid, ps.pgrp);
ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
}
TEST(spawn, posix_spawn_POSIX_SPAWN_SETSIGMASK) { #ifdefined(__GLIBC__) || defined(ANDROID_HOST_MUSL)
GTEST_SKIP() << "glibc doesn't ignore the same signals."; #else // Block SIGBUS in the parent...
sigset_t just_SIGBUS;
sigemptyset(&just_SIGBUS);
sigaddset(&just_SIGBUS, SIGBUS);
ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGBUS, nullptr));
// Ask for only SIGALRM to be blocked in the child...
sigset_t just_SIGALRM;
sigemptyset(&just_SIGALRM);
sigaddset(&just_SIGALRM, SIGALRM);
ASSERT_EQ(0, posix_spawnattr_setsigmask(&sa, &just_SIGALRM));
ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETSIGMASK));
TEST(spawn, signal_stress) { // Ensure that posix_spawn doesn't restore the caller's signal mask in the // child without first defaulting any caught signals (http://b/68707996). static pid_t parent = getpid();
setpgid(0, 0);
signal(SIGRTMIN, SIG_IGN);
pid_t pid = fork();
ASSERT_NE(-1, pid);
if (pid == 0) { for (size_t i = 0; i < 1024; ++i) {
kill(0, SIGRTMIN);
usleep(10);
}
_exit(99);
}
// We test both with and without attributes, because they used to be // different codepaths. We also test with an empty `sigdefault` set.
posix_spawnattr_t attr1;
posix_spawnattr_init(&attr1);
// We use a real-time signal because that's a tricky case for LP32 // because our sigset_t was too small.
ScopedSignalHandler ssh(SIGRTMIN, [](int) { ASSERT_EQ(getpid(), parent); });
int fd = open("/proc/version", O_RDONLY | O_CLOEXEC);
ASSERT_NE(-1, fd);
ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[0]));
ASSERT_EQ(0, posix_spawn_file_actions_adddup2(&fa, fds[1], 1)); // dup2() is a no-op when the two fds are the same, so this won't clear // O_CLOEXEC unless we're doing extra work to make that happen.
ASSERT_EQ(0, posix_spawn_file_actions_adddup2(&fa, fd, fd));
// ...and compare that to the parent. This is overkill really, since the very // fact that the child had a valid file descriptor strongly implies that we // removed O_CLOEXEC, but we may as well check that the child ended up with // the *right* file descriptor :-)
std::string expected;
ASSERT_TRUE(android::base::ReadFdToString(fd, &expected));
ASSERT_EQ(expected, content);
AssertChildExited(pid, 0);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-06-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.