signal: implement signalfd(2) - #1421
Closed
gburd wants to merge 1 commit into
Closed
Conversation
signalfd() was stubbed to return ENOSYS, so event loops that consume signals through a file descriptor (a common pattern with epoll) could not run. Implement it as a pollable special_file (modeled on eventfd) backed by a global registry of live signalfd objects. OSv is a single process, so a signalfd watches a set of signals for the whole image. kill() now checks the registry first: if any signalfd is watching the raised signal, the signal is queued to those fds (as a signalfd_siginfo) and their pollers are woken, and the signal is consumed -- the default action and any handler are skipped. This matches Linux, where a signalfd-consumed signal must be blocked and is dequeued through the fd. - signalfd(-1, mask, flags) creates a new fd; signalfd(fd, mask, flags) updates an existing one's mask. SFD_CLOEXEC and SFD_NONBLOCK are honored. - read() returns as many queued signalfd_siginfo structures as fit in the buffer, blocking (or EAGAIN when non-blocking) when the queue is empty, and rejecting a buffer smaller than one siginfo with EINVAL. - poll() reports POLLIN when signals are queued. The delivery hook (osv_signalfd_deliver) is declared in <osv/signal.hh> and called from kill() in libc/signal.cc; the stub there is removed. Add tests/tst-signalfd.cc covering delivery of a watched signal to the fd (instead of the default poweroff action), the EAGAIN/poll/queue-order paths, and the EINVAL cases. Passes on OSv under KVM (1 and 2 vCPUs); tst-sigwait and tst-sigaction continue to pass (normal signal delivery is unaffected for signals no signalfd is watching).
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
signalfd(2)was stubbed to returnENOSYS, so event loops that consumesignals through a file descriptor (a common pattern with epoll) could not run.
How
Implemented as a pollable
special_file(modeled oneventfd) backed by aglobal registry of live signalfd objects. OSv is a single process, so a
signalfd watches a set of signals for the whole image.
kill()now checks theregistry first: if any signalfd is watching the raised signal, the signal is
queued to those fds (as a
signalfd_siginfo) and their pollers are woken, andthe signal is consumed -- the default action and any handler are skipped. This
matches Linux, where a signalfd-consumed signal must be blocked and is dequeued
through the fd.
signalfd(-1, mask, flags)creates a new fd;signalfd(fd, mask, flags)updates an existing one's mask.
SFD_CLOEXECandSFD_NONBLOCKare honored.read()returns as many queuedsignalfd_siginfostructures as fit in thebuffer, blocking (or
EAGAINwhen non-blocking) when the queue is empty, andrejecting a buffer smaller than one siginfo with
EINVAL.poll()reportsPOLLINwhen signals are queued.The delivery hook (
osv_signalfd_deliver) is declared in<osv/signal.hh>andcalled from
kill()inlibc/signal.cc; the stub there is removed.Testing
tests/tst-signalfd.cccovers delivery of a watched signal to the fd (insteadof the default poweroff action), the
EAGAIN/poll/queue-order paths, and theEINVALcases. Passes on OSv under KVM (1 and 2 vCPUs).tst-sigwaitandtst-sigactioncontinue to pass, so normal signal delivery is unaffected forsignals no signalfd is watching.
Note
OSv's signal model is thread-directed and minimal; this integrates at the
process-wide
kill()delivery point, which is the right granularity for asingle-address-space unikernel. Signals raised synchronously in-thread (e.g.
faults) are a separate path and not routed to signalfd here.