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.
This commit is contained in:
Lennart Poettering 2016-10-07 12:08:51 +02:00
parent fd9b26c6f2
commit c55ae51e77

View file

@ -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) {