github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/util/signal_util.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 "test/util/signal_util.h"
    16  
    17  #include <signal.h>
    18  
    19  #include <ostream>
    20  
    21  #include "gtest/gtest.h"
    22  #include "test/util/cleanup.h"
    23  #include "test/util/posix_error.h"
    24  #include "test/util/test_util.h"
    25  
    26  namespace {
    27  
    28  struct Range {
    29    int start;
    30    int end;
    31  };
    32  
    33  // Format a Range as "start-end" or "start" for single value Ranges.
    34  static ::std::ostream& operator<<(::std::ostream& os, const Range& range) {
    35    if (range.end > range.start) {
    36      return os << range.start << '-' << range.end;
    37    }
    38  
    39    return os << range.start;
    40  }
    41  
    42  }  // namespace
    43  
    44  // Format a sigset_t as a comma separated list of numeric ranges.
    45  // Empty sigset: []
    46  // Full  sigset: [1-31,34-64]
    47  ::std::ostream& operator<<(::std::ostream& os, const sigset_t& sigset) {
    48    const char* delim = "";
    49    Range range = {0, 0};
    50  
    51    os << '[';
    52  
    53    for (int sig = 1; sig <= gvisor::testing::kMaxSignal; ++sig) {
    54      if (sigismember(&sigset, sig)) {
    55        if (range.start) {
    56          range.end = sig;
    57        } else {
    58          range.start = sig;
    59          range.end = sig;
    60        }
    61      } else if (range.start) {
    62        os << delim << range;
    63        delim = ",";
    64        range.start = 0;
    65        range.end = 0;
    66      }
    67    }
    68  
    69    if (range.start) {
    70      os << delim << range;
    71    }
    72  
    73    return os << ']';
    74  }
    75  
    76  namespace gvisor {
    77  namespace testing {
    78  
    79  PosixErrorOr<Cleanup> ScopedSigaction(int sig, struct sigaction const& sa) {
    80    struct sigaction old_sa;
    81    int rc = sigaction(sig, &sa, &old_sa);
    82    MaybeSave();
    83    if (rc < 0) {
    84      return PosixError(errno, "sigaction failed");
    85    }
    86    return Cleanup([sig, old_sa] {
    87      EXPECT_THAT(sigaction(sig, &old_sa, nullptr), SyscallSucceeds());
    88    });
    89  }
    90  
    91  PosixErrorOr<Cleanup> ScopedSignalMask(int how, sigset_t const& set) {
    92    sigset_t old;
    93    int rc = sigprocmask(how, &set, &old);
    94    MaybeSave();
    95    if (rc < 0) {
    96      return PosixError(errno, "sigprocmask failed");
    97    }
    98    return Cleanup([old] {
    99      EXPECT_THAT(sigprocmask(SIG_SETMASK, &old, nullptr), SyscallSucceeds());
   100    });
   101  }
   102  
   103  }  // namespace testing
   104  }  // namespace gvisor