diff options
author | Andrei Vagin <avagin@google.com> | 2021-05-27 15:09:27 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-05-27 15:11:49 -0700 |
commit | 17df2df75ca092342a29694739d6fbe3bf95b770 (patch) | |
tree | 7f12b06de93f1057d74f773bad886c08b10ba8e9 /test/syscalls/linux/sigstop.cc | |
parent | dd2e1f07a9c0dddcdfd5f983fc338938a4b11935 (diff) |
nanosleep has to store the finish time in the restart block
nanosleep has to count time that a thread spent in the stopped state.
PiperOrigin-RevId: 376258641
Diffstat (limited to 'test/syscalls/linux/sigstop.cc')
-rw-r--r-- | test/syscalls/linux/sigstop.cc | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/test/syscalls/linux/sigstop.cc b/test/syscalls/linux/sigstop.cc index b2fcedd62..8de03b4dc 100644 --- a/test/syscalls/linux/sigstop.cc +++ b/test/syscalls/linux/sigstop.cc @@ -123,6 +123,55 @@ void SleepIgnoreStopped(absl::Duration d) { } } +TEST(SigstopTest, RestartSyscall) { + pid_t pid; + constexpr absl::Duration kStopDelay = absl::Seconds(5); + constexpr absl::Duration kSleepDelay = absl::Seconds(15); + constexpr absl::Duration kStartupDelay = absl::Seconds(5); + constexpr absl::Duration kErrorDelay = absl::Seconds(3); + + const DisableSave ds; // Timing-related. + + pid = fork(); + if (pid == 0) { + struct timespec ts = {.tv_sec = kSleepDelay / absl::Seconds(1)}; + auto start = absl::Now(); + TEST_CHECK(nanosleep(&ts, nullptr) == 0); + auto finish = absl::Now(); + // Check that time spent stopped is counted as time spent sleeping. + TEST_CHECK(finish - start >= kSleepDelay); + TEST_CHECK(finish - start < kSleepDelay + kErrorDelay); + _exit(kChildMainThreadExitCode); + } + ASSERT_THAT(pid, SyscallSucceeds()); + + // Wait for the child subprocess to start sleeping before stopping it. + absl::SleepFor(kStartupDelay); + ASSERT_THAT(kill(pid, SIGSTOP), SyscallSucceeds()); + int status; + EXPECT_THAT(RetryEINTR(waitpid)(pid, &status, WUNTRACED), + SyscallSucceedsWithValue(pid)); + EXPECT_TRUE(WIFSTOPPED(status)); + EXPECT_EQ(SIGSTOP, WSTOPSIG(status)); + + // Sleep for shorter than the sleep in the child subprocess. + absl::SleepFor(kStopDelay); + ASSERT_THAT(RetryEINTR(waitpid)(pid, &status, WNOHANG), + SyscallSucceedsWithValue(0)); + + // Resume the child. + ASSERT_THAT(kill(pid, SIGCONT), SyscallSucceeds()); + + EXPECT_THAT(RetryEINTR(waitpid)(pid, &status, WCONTINUED), + SyscallSucceedsWithValue(pid)); + EXPECT_TRUE(WIFCONTINUED(status)); + + // Expect it to die. + ASSERT_THAT(RetryEINTR(waitpid)(pid, &status, 0), SyscallSucceeds()); + ASSERT_TRUE(WIFEXITED(status)); + ASSERT_EQ(WEXITSTATUS(status), kChildMainThreadExitCode); +} + void RunChild() { // Start another thread that attempts to call exit_group with a different // error code, in order to verify that SIGSTOP stops this thread as well. |