diff options
author | Adin Scannell <ascannell@google.com> | 2019-10-10 12:45:34 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2019-10-10 12:51:22 -0700 |
commit | f8b18593198cf7ca1adfca19d846e66080b07942 (patch) | |
tree | 253ea05b2729fbac2e7ddb25e3030474535ab782 | |
parent | 14952d01fb5fa03a40dbb241b4c12f5a400a3577 (diff) |
Fix signalfd polling.
The signalfd descriptors otherwise always show as available. This can lead
programs to spin, assuming they are looking to see what signals are pending.
Updates #139
PiperOrigin-RevId: 274017890
-rw-r--r-- | pkg/sentry/kernel/signalfd/signalfd.go | 5 | ||||
-rw-r--r-- | test/syscalls/linux/signalfd.cc | 17 |
2 files changed, 21 insertions, 1 deletions
diff --git a/pkg/sentry/kernel/signalfd/signalfd.go b/pkg/sentry/kernel/signalfd/signalfd.go index 06fd5ec88..4b08d7d72 100644 --- a/pkg/sentry/kernel/signalfd/signalfd.go +++ b/pkg/sentry/kernel/signalfd/signalfd.go @@ -121,7 +121,10 @@ func (s *SignalOperations) Read(ctx context.Context, _ *fs.File, dst usermem.IOS // Readiness implements waiter.Waitable.Readiness. func (s *SignalOperations) Readiness(mask waiter.EventMask) waiter.EventMask { - return mask & waiter.EventIn + if mask&waiter.EventIn != 0 && s.target.PendingSignals()&s.Mask() != 0 { + return waiter.EventIn // Pending signals. + } + return 0 } // EventRegister implements waiter.Waitable.EventRegister. diff --git a/test/syscalls/linux/signalfd.cc b/test/syscalls/linux/signalfd.cc index 54c598627..9379d5878 100644 --- a/test/syscalls/linux/signalfd.cc +++ b/test/syscalls/linux/signalfd.cc @@ -312,6 +312,23 @@ TEST(Signalfd, KillStillKills) { EXPECT_EXIT(tgkill(getpid(), gettid(), SIGKILL), KilledBySignal(SIGKILL), ""); } +TEST(Signalfd, Ppoll) { + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGKILL); + FileDescriptor fd = + ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask, SFD_CLOEXEC)); + + // Ensure that the given ppoll blocks. + struct pollfd pfd = {}; + pfd.fd = fd.get(); + pfd.events = POLLIN; + struct timespec timeout = {}; + timeout.tv_sec = 1; + EXPECT_THAT(RetryEINTR(ppoll)(&pfd, 1, &timeout, &mask), + SyscallSucceedsWithValue(0)); +} + } // namespace } // namespace testing |