gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/base_poll_test.h (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 #ifndef GVISOR_TEST_SYSCALLS_BASE_POLL_TEST_H_ 16 #define GVISOR_TEST_SYSCALLS_BASE_POLL_TEST_H_ 17 18 #include <signal.h> 19 #include <sys/syscall.h> 20 #include <sys/types.h> 21 #include <syscall.h> 22 #include <time.h> 23 #include <unistd.h> 24 25 #include <memory> 26 27 #include "gtest/gtest.h" 28 #include "absl/synchronization/mutex.h" 29 #include "absl/time/time.h" 30 #include "test/util/logging.h" 31 #include "test/util/signal_util.h" 32 #include "test/util/thread_util.h" 33 34 namespace gvisor { 35 namespace testing { 36 37 // TimerThread is a cancelable timer. 38 class TimerThread { 39 public: 40 TimerThread(absl::Time deadline, pid_t tgid, pid_t tid) 41 : thread_([=] { 42 mu_.Lock(); 43 mu_.AwaitWithDeadline(absl::Condition(&cancel_), deadline); 44 if (!cancel_) { 45 TEST_PCHECK(tgkill(tgid, tid, SIGALRM) == 0); 46 } 47 mu_.Unlock(); 48 }) {} 49 50 ~TimerThread() { Cancel(); } 51 52 void Cancel() { 53 absl::MutexLock ml(&mu_); 54 cancel_ = true; 55 } 56 57 private: 58 mutable absl::Mutex mu_; 59 bool cancel_ ABSL_GUARDED_BY(mu_) = false; 60 61 // Must be last to ensure that the destructor for the thread is run before 62 // any other member of the object is destroyed. 63 ScopedThread thread_; 64 }; 65 66 // Base test fixture for poll, select, ppoll, and pselect tests. 67 // 68 // This fixture makes use of SIGALRM. The handler is saved in SetUp() and 69 // restored in TearDown(). 70 class BasePollTest : public ::testing::Test { 71 protected: 72 BasePollTest(); 73 ~BasePollTest() override; 74 75 // Sets a timer that will send a signal to the calling thread after 76 // `duration`. 77 void SetTimer(absl::Duration duration); 78 79 // Returns true if the timer has fired. 80 bool TimerFired() const; 81 82 // Stops the pending timer (if any) and clear the "fired" state. 83 void ClearTimer(); 84 85 private: 86 // Thread that implements the timer. If the timer is stopped, timer_ is null. 87 // 88 // We have to use a thread for this purpose because tests using this fixture 89 // expect to be interrupted by the timer signal, but itimers/alarm(2) send 90 // thread-group-directed signals, which may be handled by any thread in the 91 // test process. 92 std::unique_ptr<TimerThread> timer_; 93 94 // The original SIGALRM handler, to restore in destructor. 95 struct sigaction original_alarm_sa_; 96 }; 97 98 } // namespace testing 99 } // namespace gvisor 100 101 #endif // GVISOR_TEST_SYSCALLS_BASE_POLL_TEST_H_