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 }