Convert EventMask to uint64

It is used for signalfd where the maximum signal is 64.

PiperOrigin-RevId: 290331008
This commit is contained in:
Andrei Vagin
2020-01-17 13:32:51 -08:00
committed by gVisor bot
parent 23fa847910
commit 9073521098
3 changed files with 74 additions and 48 deletions
+1 -1
View File
@@ -62,7 +62,7 @@ import (
)
// EventMask represents io events as used in the poll() syscall.
type EventMask uint16
type EventMask uint64
// Events that waiters can wait on. The meaning is the same as those in the
// poll() syscall.
+2
View File
@@ -380,6 +380,8 @@ syscall_test(test = "//test/syscalls/linux:rseq_test")
syscall_test(test = "//test/syscalls/linux:rtsignal_test")
syscall_test(test = "//test/syscalls/linux:signalfd_test")
syscall_test(test = "//test/syscalls/linux:sched_test")
syscall_test(test = "//test/syscalls/linux:sched_yield_test")
+71 -47
View File
@@ -39,6 +39,7 @@ namespace testing {
namespace {
constexpr int kSigno = SIGUSR1;
constexpr int kSignoMax = 64; // SIGRTMAX
constexpr int kSignoAlt = SIGUSR2;
// Returns a new signalfd.
@@ -51,41 +52,45 @@ inline PosixErrorOr<FileDescriptor> NewSignalFD(sigset_t* mask, int flags = 0) {
return FileDescriptor(fd);
}
TEST(Signalfd, Basic) {
class SignalfdTest : public ::testing::TestWithParam<int> {};
TEST_P(SignalfdTest, Basic) {
int signo = GetParam();
// Create the signalfd.
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, kSigno);
sigaddset(&mask, signo);
FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask, 0));
// Deliver the blocked signal.
const auto scoped_sigmask =
ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_BLOCK, kSigno));
ASSERT_THAT(tgkill(getpid(), gettid(), kSigno), SyscallSucceeds());
ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_BLOCK, signo));
ASSERT_THAT(tgkill(getpid(), gettid(), signo), SyscallSucceeds());
// We should now read the signal.
struct signalfd_siginfo rbuf;
ASSERT_THAT(read(fd.get(), &rbuf, sizeof(rbuf)),
SyscallSucceedsWithValue(sizeof(rbuf)));
EXPECT_EQ(rbuf.ssi_signo, kSigno);
EXPECT_EQ(rbuf.ssi_signo, signo);
}
TEST(Signalfd, MaskWorks) {
TEST_P(SignalfdTest, MaskWorks) {
int signo = GetParam();
// Create two signalfds with different masks.
sigset_t mask1, mask2;
sigemptyset(&mask1);
sigemptyset(&mask2);
sigaddset(&mask1, kSigno);
sigaddset(&mask1, signo);
sigaddset(&mask2, kSignoAlt);
FileDescriptor fd1 = ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask1, 0));
FileDescriptor fd2 = ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask2, 0));
// Deliver the two signals.
const auto scoped_sigmask1 =
ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_BLOCK, kSigno));
ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_BLOCK, signo));
const auto scoped_sigmask2 =
ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_BLOCK, kSignoAlt));
ASSERT_THAT(tgkill(getpid(), gettid(), kSigno), SyscallSucceeds());
ASSERT_THAT(tgkill(getpid(), gettid(), signo), SyscallSucceeds());
ASSERT_THAT(tgkill(getpid(), gettid(), kSignoAlt), SyscallSucceeds());
// We should see the signals on the appropriate signalfds.
@@ -98,7 +103,7 @@ TEST(Signalfd, MaskWorks) {
EXPECT_EQ(rbuf2.ssi_signo, kSignoAlt);
ASSERT_THAT(read(fd1.get(), &rbuf1, sizeof(rbuf1)),
SyscallSucceedsWithValue(sizeof(rbuf1)));
EXPECT_EQ(rbuf1.ssi_signo, kSigno);
EXPECT_EQ(rbuf1.ssi_signo, signo);
}
TEST(Signalfd, Cloexec) {
@@ -111,11 +116,12 @@ TEST(Signalfd, Cloexec) {
EXPECT_THAT(fcntl(fd.get(), F_GETFD), SyscallSucceedsWithValue(FD_CLOEXEC));
}
TEST(Signalfd, Blocking) {
TEST_P(SignalfdTest, Blocking) {
int signo = GetParam();
// Create the signalfd in blocking mode.
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, kSigno);
sigaddset(&mask, signo);
FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask, 0));
// Shared tid variable.
@@ -136,7 +142,7 @@ TEST(Signalfd, Blocking) {
struct signalfd_siginfo rbuf;
ASSERT_THAT(read(fd.get(), &rbuf, sizeof(rbuf)),
SyscallSucceedsWithValue(sizeof(rbuf)));
EXPECT_EQ(rbuf.ssi_signo, kSigno);
EXPECT_EQ(rbuf.ssi_signo, signo);
});
// Wait until blocked.
@@ -149,20 +155,21 @@ TEST(Signalfd, Blocking) {
//
// See gvisor.dev/issue/139.
if (IsRunningOnGvisor()) {
ASSERT_THAT(tgkill(getpid(), gettid(), kSigno), SyscallSucceeds());
ASSERT_THAT(tgkill(getpid(), gettid(), signo), SyscallSucceeds());
} else {
ASSERT_THAT(tgkill(getpid(), tid, kSigno), SyscallSucceeds());
ASSERT_THAT(tgkill(getpid(), tid, signo), SyscallSucceeds());
}
// Ensure that it was received.
t.Join();
}
TEST(Signalfd, ThreadGroup) {
TEST_P(SignalfdTest, ThreadGroup) {
int signo = GetParam();
// Create the signalfd in blocking mode.
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, kSigno);
sigaddset(&mask, signo);
FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask, 0));
// Shared variable.
@@ -176,7 +183,7 @@ TEST(Signalfd, ThreadGroup) {
struct signalfd_siginfo rbuf;
ASSERT_THAT(read(fd.get(), &rbuf, sizeof(rbuf)),
SyscallSucceedsWithValue(sizeof(rbuf)));
EXPECT_EQ(rbuf.ssi_signo, kSigno);
EXPECT_EQ(rbuf.ssi_signo, signo);
// Wait for the other thread.
absl::MutexLock ml(&mu);
@@ -185,7 +192,7 @@ TEST(Signalfd, ThreadGroup) {
});
// Deliver the signal to the threadgroup.
ASSERT_THAT(kill(getpid(), kSigno), SyscallSucceeds());
ASSERT_THAT(kill(getpid(), signo), SyscallSucceeds());
// Wait for the first thread to process.
{
@@ -194,13 +201,13 @@ TEST(Signalfd, ThreadGroup) {
}
// Deliver to the thread group again (other thread still exists).
ASSERT_THAT(kill(getpid(), kSigno), SyscallSucceeds());
ASSERT_THAT(kill(getpid(), signo), SyscallSucceeds());
// Ensure that we can also receive it.
struct signalfd_siginfo rbuf;
ASSERT_THAT(read(fd.get(), &rbuf, sizeof(rbuf)),
SyscallSucceedsWithValue(sizeof(rbuf)));
EXPECT_EQ(rbuf.ssi_signo, kSigno);
EXPECT_EQ(rbuf.ssi_signo, signo);
// Mark the test as done.
{
@@ -212,11 +219,12 @@ TEST(Signalfd, ThreadGroup) {
t.Join();
}
TEST(Signalfd, Nonblock) {
TEST_P(SignalfdTest, Nonblock) {
int signo = GetParam();
// Create the signalfd in non-blocking mode.
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, kSigno);
sigaddset(&mask, signo);
FileDescriptor fd =
ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask, SFD_NONBLOCK));
@@ -227,20 +235,21 @@ TEST(Signalfd, Nonblock) {
// Block and deliver the signal.
const auto scoped_sigmask =
ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_BLOCK, kSigno));
ASSERT_THAT(tgkill(getpid(), gettid(), kSigno), SyscallSucceeds());
ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_BLOCK, signo));
ASSERT_THAT(tgkill(getpid(), gettid(), signo), SyscallSucceeds());
// Ensure that a read actually works.
ASSERT_THAT(read(fd.get(), &rbuf, sizeof(rbuf)),
SyscallSucceedsWithValue(sizeof(rbuf)));
EXPECT_EQ(rbuf.ssi_signo, kSigno);
EXPECT_EQ(rbuf.ssi_signo, signo);
// Should block again.
EXPECT_THAT(read(fd.get(), &rbuf, sizeof(rbuf)),
SyscallFailsWithErrno(EWOULDBLOCK));
}
TEST(Signalfd, SetMask) {
TEST_P(SignalfdTest, SetMask) {
int signo = GetParam();
// Create the signalfd matching nothing.
sigset_t mask;
sigemptyset(&mask);
@@ -249,8 +258,8 @@ TEST(Signalfd, SetMask) {
// Block and deliver a signal.
const auto scoped_sigmask =
ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_BLOCK, kSigno));
ASSERT_THAT(tgkill(getpid(), gettid(), kSigno), SyscallSucceeds());
ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_BLOCK, signo));
ASSERT_THAT(tgkill(getpid(), gettid(), signo), SyscallSucceeds());
// We should have nothing.
struct signalfd_siginfo rbuf;
@@ -258,29 +267,30 @@ TEST(Signalfd, SetMask) {
SyscallFailsWithErrno(EWOULDBLOCK));
// Change the signal mask.
sigaddset(&mask, kSigno);
sigaddset(&mask, signo);
ASSERT_THAT(signalfd(fd.get(), &mask, 0), SyscallSucceeds());
// We should now have the signal.
ASSERT_THAT(read(fd.get(), &rbuf, sizeof(rbuf)),
SyscallSucceedsWithValue(sizeof(rbuf)));
EXPECT_EQ(rbuf.ssi_signo, kSigno);
EXPECT_EQ(rbuf.ssi_signo, signo);
}
TEST(Signalfd, Poll) {
TEST_P(SignalfdTest, Poll) {
int signo = GetParam();
// Create the signalfd.
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, kSigno);
sigaddset(&mask, signo);
FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask, 0));
// Block the signal, and start a thread to deliver it.
const auto scoped_sigmask =
ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_BLOCK, kSigno));
ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_BLOCK, signo));
pid_t orig_tid = gettid();
ScopedThread t([&] {
absl::SleepFor(absl::Seconds(5));
ASSERT_THAT(tgkill(getpid(), orig_tid, kSigno), SyscallSucceeds());
ASSERT_THAT(tgkill(getpid(), orig_tid, signo), SyscallSucceeds());
});
// Start polling for the signal. We expect that it is not available at the
@@ -297,19 +307,18 @@ TEST(Signalfd, Poll) {
SyscallSucceedsWithValue(sizeof(rbuf)));
}
TEST(Signalfd, KillStillKills) {
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGKILL);
FileDescriptor fd =
ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask, SFD_CLOEXEC));
// Just because there is a signalfd, we shouldn't see any change in behavior
// for unblockable signals. It's easier to test this with SIGKILL.
const auto scoped_sigmask =
ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_BLOCK, SIGKILL));
EXPECT_EXIT(tgkill(getpid(), gettid(), SIGKILL), KilledBySignal(SIGKILL), "");
std::string PrintSigno(::testing::TestParamInfo<int> info) {
switch (info.param) {
case kSigno:
return "kSigno";
case kSignoMax:
return "kSignoMax";
default:
return absl::StrCat(info.param);
}
}
INSTANTIATE_TEST_SUITE_P(Signalfd, SignalfdTest,
::testing::Values(kSigno, kSignoMax), PrintSigno);
TEST(Signalfd, Ppoll) {
sigset_t mask;
@@ -328,6 +337,20 @@ TEST(Signalfd, Ppoll) {
SyscallSucceedsWithValue(0));
}
TEST(Signalfd, KillStillKills) {
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGKILL);
FileDescriptor fd =
ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask, SFD_CLOEXEC));
// Just because there is a signalfd, we shouldn't see any change in behavior
// for unblockable signals. It's easier to test this with SIGKILL.
const auto scoped_sigmask =
ASSERT_NO_ERRNO_AND_VALUE(ScopedSignalMask(SIG_BLOCK, SIGKILL));
EXPECT_EXIT(tgkill(getpid(), gettid(), SIGKILL), KilledBySignal(SIGKILL), "");
}
} // namespace
} // namespace testing
@@ -340,6 +363,7 @@ int main(int argc, char** argv) {
sigset_t set;
sigemptyset(&set);
sigaddset(&set, gvisor::testing::kSigno);
sigaddset(&set, gvisor::testing::kSignoMax);
sigaddset(&set, gvisor::testing::kSignoAlt);
TEST_PCHECK(sigprocmask(SIG_BLOCK, &set, nullptr) == 0);