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_