gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/alarm.cc (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #include <signal.h>
    16  #include <unistd.h>
    17  
    18  #include "gtest/gtest.h"
    19  #include "absl/time/clock.h"
    20  #include "absl/time/time.h"
    21  #include "test/util/file_descriptor.h"
    22  #include "test/util/logging.h"
    23  #include "test/util/signal_util.h"
    24  #include "test/util/test_util.h"
    25  #include "test/util/thread_util.h"
    26  
    27  namespace gvisor {
    28  namespace testing {
    29  
    30  namespace {
    31  
    32  // N.B. Below, main blocks SIGALRM. Test cases must unblock it if they want
    33  // delivery.
    34  
    35  void do_nothing_handler(int sig, siginfo_t* siginfo, void* arg) {}
    36  
    37  // No random save as the test relies on alarm timing. Cooperative save tests
    38  // already cover the save between alarm and read.
    39  TEST(AlarmTest, Interrupt) {
    40    int pipe_fds[2];
    41    ASSERT_THAT(pipe(pipe_fds), SyscallSucceeds());
    42  
    43    FileDescriptor read_fd(pipe_fds[0]);
    44    FileDescriptor write_fd(pipe_fds[1]);
    45  
    46    // Use a signal handler that interrupts but does nothing rather than using the
    47    // default terminate action.
    48    struct sigaction sa;
    49    sa.sa_sigaction = do_nothing_handler;
    50    sigfillset(&sa.sa_mask);
    51    sa.sa_flags = 0;
    52    auto sa_cleanup = ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(SIGALRM, sa));
    53  
    54    // Actually allow SIGALRM delivery.
    55    auto mask_cleanup =
    56        ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_UNBLOCK, SIGALRM));
    57  
    58    // Alarm in 20 second, which should be well after read blocks below.
    59    ASSERT_THAT(alarm(20), SyscallSucceeds());
    60  
    61    char buf;
    62    ASSERT_THAT(read(read_fd.get(), &buf, 1), SyscallFailsWithErrno(EINTR));
    63  }
    64  
    65  /* Count of the number of SIGALARMS handled. */
    66  static volatile int alarms_received = 0;
    67  
    68  void inc_alarms_handler(int sig, siginfo_t* siginfo, void* arg) {
    69    alarms_received++;
    70  }
    71  
    72  // No random save as the test relies on alarm timing. Cooperative save tests
    73  // already cover the save between alarm and read.
    74  TEST(AlarmTest, Restart) {
    75    alarms_received = 0;
    76  
    77    int pipe_fds[2];
    78    ASSERT_THAT(pipe(pipe_fds), SyscallSucceeds());
    79  
    80    FileDescriptor read_fd(pipe_fds[0]);
    81    // Write end closed by thread below.
    82  
    83    struct sigaction sa;
    84    sa.sa_sigaction = inc_alarms_handler;
    85    sigfillset(&sa.sa_mask);
    86    sa.sa_flags = SA_RESTART;
    87    auto sa_cleanup = ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(SIGALRM, sa));
    88  
    89    // Spawn a thread to eventually unblock the read below.
    90    ScopedThread t([pipe_fds] {
    91      absl::SleepFor(absl::Seconds(30));
    92      EXPECT_THAT(close(pipe_fds[1]), SyscallSucceeds());
    93    });
    94  
    95    // Actually allow SIGALRM delivery.
    96    auto mask_cleanup =
    97        ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_UNBLOCK, SIGALRM));
    98  
    99    // Alarm in 20 second, which should be well after read blocks below, but
   100    // before it returns.
   101    ASSERT_THAT(alarm(20), SyscallSucceeds());
   102  
   103    // Read and eventually get an EOF from the writer closing.  If SA_RESTART
   104    // didn't work, then the alarm would not have fired and we wouldn't increment
   105    // our alarms_received count in our signal handler, or we would have not
   106    // restarted the syscall gracefully, which we expect below in order to be
   107    // able to get the final EOF on the pipe.
   108    char buf;
   109    ASSERT_THAT(read(read_fd.get(), &buf, 1), SyscallSucceeds());
   110    EXPECT_EQ(alarms_received, 1);
   111  
   112    t.Join();
   113  }
   114  
   115  // No random save as the test relies on alarm timing. Cooperative save tests
   116  // already cover the save between alarm and pause.
   117  TEST(AlarmTest, SaSiginfo) {
   118    // Use a signal handler that interrupts but does nothing rather than using the
   119    // default terminate action.
   120    struct sigaction sa;
   121    sa.sa_sigaction = do_nothing_handler;
   122    sigfillset(&sa.sa_mask);
   123    sa.sa_flags = SA_SIGINFO;
   124    auto sa_cleanup = ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(SIGALRM, sa));
   125  
   126    // Actually allow SIGALRM delivery.
   127    auto mask_cleanup =
   128        ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_UNBLOCK, SIGALRM));
   129  
   130    // Alarm in 20 second, which should be well after pause blocks below.
   131    ASSERT_THAT(alarm(20), SyscallSucceeds());
   132    ASSERT_THAT(pause(), SyscallFailsWithErrno(EINTR));
   133  }
   134  
   135  #ifndef SA_INTERRUPT
   136  #define SA_INTERRUPT 0x20000000
   137  #endif  // SA_INTERRUPT
   138  
   139  // No random save as the test relies on alarm timing. Cooperative save tests
   140  // already cover the save between alarm and pause.
   141  TEST(AlarmTest, SaInterrupt) {
   142    // Use a signal handler that interrupts but does nothing rather than using the
   143    // default terminate action.
   144    struct sigaction sa;
   145    sa.sa_sigaction = do_nothing_handler;
   146    sigfillset(&sa.sa_mask);
   147    sa.sa_flags = SA_INTERRUPT;
   148    auto sa_cleanup = ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(SIGALRM, sa));
   149  
   150    // Actually allow SIGALRM delivery.
   151    auto mask_cleanup =
   152        ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_UNBLOCK, SIGALRM));
   153  
   154    // Alarm in 20 second, which should be well after pause blocks below.
   155    ASSERT_THAT(alarm(20), SyscallSucceeds());
   156    ASSERT_THAT(pause(), SyscallFailsWithErrno(EINTR));
   157  }
   158  
   159  TEST(AlarmTest, UserModeSpinning) {
   160    alarms_received = 0;
   161  
   162    struct sigaction sa = {};
   163    sa.sa_sigaction = inc_alarms_handler;
   164    sigfillset(&sa.sa_mask);
   165    sa.sa_flags = SA_SIGINFO;
   166    auto sa_cleanup = ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(SIGALRM, sa));
   167  
   168    // Actually allow SIGALRM delivery.
   169    auto mask_cleanup =
   170        ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_UNBLOCK, SIGALRM));
   171  
   172    // Alarm in 20 second, which should be well into the loop below.
   173    ASSERT_THAT(alarm(20), SyscallSucceeds());
   174    // Make sure that the signal gets delivered even if we are spinning in user
   175    // mode when it arrives.
   176    while (!alarms_received) {
   177    }
   178  }
   179  
   180  }  // namespace
   181  
   182  }  // namespace testing
   183  }  // namespace gvisor
   184  
   185  int main(int argc, char** argv) {
   186    // These tests depend on delivering SIGALRM to the main thread. Block SIGALRM
   187    // so that any other threads created by TestInit will also have SIGALRM
   188    // blocked.
   189    sigset_t set;
   190    sigemptyset(&set);
   191    sigaddset(&set, SIGALRM);
   192    TEST_PCHECK(sigprocmask(SIG_BLOCK, &set, nullptr) == 0);
   193  
   194    gvisor::testing::TestInit(&argc, &argv);
   195    return gvisor::testing::RunAllTests();
   196  }