From 3b20802be780b791caa86b7b6aa8ad49315f2f8c Mon Sep 17 00:00:00 2001 From: Krister Johansen Date: Tue, 7 May 2019 15:30:25 -0700 Subject: [PATCH] rngd exits after being stopped and resumed Linux has documented but somewhat unusual behavior around SIGSTOP/SIGCONT and certain syscalls, of which epoll_wait(2) is one. In this particular case, rngd exited unexpectedly after getting ptrace'd mid-epoll_wait. Fix this by handling EINTR from this syscall, and continuing to add entropy and wait. Signed-off-by: Krister Johansen --- pkg/rngd/cmd/rngd/main.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkg/rngd/cmd/rngd/main.go b/pkg/rngd/cmd/rngd/main.go index 93136d233..af1fcdaa0 100644 --- a/pkg/rngd/cmd/rngd/main.go +++ b/pkg/rngd/cmd/rngd/main.go @@ -9,6 +9,7 @@ import ( "flag" "log" "os" + "syscall" "unsafe" "golang.org/x/sys/unix" @@ -62,6 +63,17 @@ func main() { // sleep until we can write more nevents, err := unix.EpollWait(epfd, events[:], timeout) if err != nil { + // According to signal(7) on Linux, epoll_wait(2) returns EINTR if + // the system call is interrupted by a SIGSTOP and then resumed by + // a SIGCONT, even if the default signal handler remains in place. + // This is a long-winded way of saying that we must handle EINTR + // here, or else the program may exit after being stopped and then + // resumed by a signal, a debugger, or ptrace. + if e, ok := err.(syscall.Errno); ok { + if e.Temporary() { + continue + } + } log.Fatalf("epoll wait error: %v", err) } if nevents == 1 && events[0].Events&unix.EPOLLOUT == unix.EPOLLOUT {