summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-10-07 12:08:51 +0200
committerLennart Poettering <lennart@poettering.net>2016-10-07 12:08:51 +0200
commitc55ae51e77e1fc56fde7bc3466dd2021ff3856cb (patch)
treed25b394f22ddd77bb162ceb470ca12ab924ad09b
parentfd9b26c6f208dda8e7235c7c793df2b5f162d015 (diff)
manager: don't ever busy loop when we get a notification message we can't process
If the kernel doesn't permit us to dequeue/process an incoming notification datagram message it's still better to stop processing the notification messages altogether than to enter a busy loop where we keep getting notified but can't do a thing about it. With this change, manager_dispatch_notify_fd() behaviour is changed like this: - if an error indicating a spurious wake-up is seen on recvmsg(), ignore it (EAGAIN/EINTR) - if any other error is seen on recvmsg() propagate it, thus disabling processing of further wakeups - if any error is seen on later code in the function, warn about it but do not propagate it, as in this cas we're not going to busy loop as the offending message is already dequeued.
-rw-r--r--src/core/manager.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/src/core/manager.c b/src/core/manager.c
index 5253cb3712..ab65d630a1 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1722,14 +1722,13 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (n < 0) {
- if (!IN_SET(errno, EAGAIN, EINTR))
- log_error("Failed to receive notification message: %m");
+ if (IN_SET(errno, EAGAIN, EINTR))
+ return 0; /* Spurious wakeup, try again */
- /* It's not an option to return an error here since it
- * would disable the notification handler entirely. Services
- * wouldn't be able to send the WATCHDOG message for
- * example... */
- return 0;
+ /* If this is any other, real error, then let's stop processing this socket. This of course means we
+ * won't take notification messages anymore, but that's still better than busy looping around this:
+ * being woken up over and over again but being unable to actually read the message off the socket. */
+ return log_error_errno(errno, "Failed to receive notification message: %m");
}
CMSG_FOREACH(cmsg, &msghdr) {