summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdin Scannell <ascannell@google.com>2019-10-10 12:45:34 -0700
committergVisor bot <gvisor-bot@google.com>2019-10-10 12:51:22 -0700
commitf8b18593198cf7ca1adfca19d846e66080b07942 (patch)
tree253ea05b2729fbac2e7ddb25e3030474535ab782
parent14952d01fb5fa03a40dbb241b4c12f5a400a3577 (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.go5
-rw-r--r--test/syscalls/linux/signalfd.cc17
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