| // Copyright 2026 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include <sys/syscall.h> | |
| #include <sys/time.h> | |
| #include <unistd.h> | |
| #include <cerrno> | |
| #include <csignal> | |
| #include <cstdlib> | |
| #include <ctime> | |
| #include <gtest/gtest.h> | |
| #include "src/starnix/tests/syscalls/cpp/syscall_matchers.h" | |
| int main(int argc, char** argv) { | |
| if (argc != 2) { | |
| return EXIT_FAILURE; | |
| } | |
| int kernel_timer_id = std::atoi(argv[1]); | |
| // POSIX timers created via timer_create(2) are not preserved across execve(2). | |
| struct itimerspec its = {}; | |
| EXPECT_THAT(syscall(SYS_timer_gettime, kernel_timer_id, &its), SyscallFailsWithErrno(EINVAL)); | |
| EXPECT_THAT(syscall(SYS_timer_delete, kernel_timer_id), SyscallFailsWithErrno(EINVAL)); | |
| // Interval timers (setitimer(2)) are preserved across execve(2). | |
| struct itimerval itv = {}; | |
| EXPECT_THAT(getitimer(ITIMER_REAL, &itv), SyscallSucceeds()); | |
| EXPECT_GT(itv.it_value.tv_sec, 0); | |
| struct itimerval zero_itv = {}; | |
| EXPECT_THAT(setitimer(ITIMER_REAL, &zero_itv, nullptr), SyscallSucceeds()); | |
| // Verify that new POSIX timers can be created after execve(2). Linux is observed to not reset | |
| // the per-process timer ID counter across execve(2), so the new timer receives the next | |
| // sequential ID after the pre-exec timer. | |
| int new_timer_id = -1; | |
| struct sigevent sev = {}; | |
| sev.sigev_notify = SIGEV_NONE; | |
| EXPECT_THAT(syscall(SYS_timer_create, CLOCK_MONOTONIC, &sev, &new_timer_id), SyscallSucceeds()); | |
| EXPECT_EQ(new_timer_id, kernel_timer_id + 1); | |
| EXPECT_THAT(syscall(SYS_timer_delete, new_timer_id), SyscallSucceeds()); | |
| return ::testing::Test::HasFailure() ? EXIT_FAILURE : EXIT_SUCCESS; | |
| } |