From 261f9c7e6c2c2acfd3d23ff3c9a5344faf65b9bd Mon Sep 17 00:00:00 2001 From: gVisor bot Date: Mon, 7 Mar 2022 15:14:42 -0800 Subject: [PATCH] Test that all threads in thread group terminate Tests that when one thread calls `_exit()`, all threads in the thread group are terminated. PiperOrigin-RevId: 433052210 --- test/syscalls/linux/BUILD | 4 +++- test/syscalls/linux/exit.cc | 38 +++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD index 6f2f70bcc..37c6946c8 100644 --- a/test/syscalls/linux/BUILD +++ b/test/syscalls/linux/BUILD @@ -749,10 +749,12 @@ cc_binary( linkstatic = 1, deps = [ "//test/util:file_descriptor", + "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/time", gtest, - "//test/util:test_main", + "//test/util:multiprocess_util", "//test/util:test_util", + "//test/util:thread_util", "//test/util:time_util", ], ) diff --git a/test/syscalls/linux/exit.cc b/test/syscalls/linux/exit.cc index d52ea786b..37b927cfd 100644 --- a/test/syscalls/linux/exit.cc +++ b/test/syscalls/linux/exit.cc @@ -16,11 +16,17 @@ #include #include "gtest/gtest.h" +#include "absl/flags/flag.h" #include "absl/time/time.h" #include "test/util/file_descriptor.h" +#include "test/util/multiprocess_util.h" #include "test/util/test_util.h" +#include "test/util/thread_util.h" #include "test/util/time_util.h" +ABSL_FLAG(bool, test_child, false, + "If true, run the ExitAllThreads child workload."); + namespace gvisor { namespace testing { @@ -72,7 +78,39 @@ TEST(ExitTest, CloseFds) { SyscallSucceedsWithValue(0)); } +TEST(ExitTest, ExitAllThreads) { + pid_t child_pid = -1; + int execve_errno = 0; + auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( + ForkAndExec("/proc/self/exe", {"/proc/self/exe", "--test_child"}, {}, + nullptr, &child_pid, &execve_errno)); + ASSERT_GT(child_pid, 0); + ASSERT_EQ(execve_errno, 0); + + int status; + EXPECT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); + EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) << status; +} + +void RunChild() { + ScopedThread t([] { _exit(0); }); + t.Join(); + // Should not be reached + abort(); +} + } // namespace } // namespace testing } // namespace gvisor + +int main(int argc, char** argv) { + gvisor::testing::TestInit(&argc, &argv); + + if (absl::GetFlag(FLAGS_test_child)) { + gvisor::testing::RunChild(); + return 1; + } + + return gvisor::testing::RunAllTests(); +}