mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-03 13:47:04 +03:00
core: fix priority ordering in notify-handling
Currently, we dispatch NOTIFY messages in a tight loop. Regardless how much data is incoming, we always dispatch everything that is queued. This, however, completely breaks priority event-handling of sd-event. When dispatching one NOTIFY event, another completely different event might fire, or might be queued by the NOTIFY handling. However, this event will not get dispatched until all other further NOTIFY messages are handled. Those might even arrive _after_ the other event fired, and as such completely break priority ordering of sd-event (which several code paths rely on). Break this by never dispatching multiple messages. Just return after each message that was read and let sd-event handle everything else. (The patch looks scarier that it is. It basically just drops the for(;;) loop and re-indents the loop-content.)
This commit is contained in:
parent
df5b3e1840
commit
b215b0ede1
@ -1509,20 +1509,9 @@ static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, char *
|
||||
}
|
||||
|
||||
static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
|
||||
Manager *m = userdata;
|
||||
ssize_t n;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(m->notify_fd == fd);
|
||||
|
||||
if (revents != EPOLLIN) {
|
||||
log_warning("Got unexpected poll event for notify fd.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
_cleanup_fdset_free_ FDSet *fds = NULL;
|
||||
Manager *m = userdata;
|
||||
|
||||
char buf[NOTIFY_BUFFER_MAX+1];
|
||||
struct iovec iovec = {
|
||||
.iov_base = buf,
|
||||
@ -1539,17 +1528,27 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof(control),
|
||||
};
|
||||
|
||||
struct cmsghdr *cmsg;
|
||||
struct ucred *ucred = NULL;
|
||||
bool found = false;
|
||||
Unit *u1, *u2, *u3;
|
||||
int *fd_array = NULL;
|
||||
int r, *fd_array = NULL;
|
||||
unsigned n_fds = 0;
|
||||
ssize_t n;
|
||||
|
||||
assert(m);
|
||||
assert(m->notify_fd == fd);
|
||||
|
||||
if (revents != EPOLLIN) {
|
||||
log_warning("Got unexpected poll event for notify fd.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (n < 0) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
break;
|
||||
return 0;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
@ -1580,12 +1579,12 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
|
||||
|
||||
if (!ucred || ucred->pid <= 0) {
|
||||
log_warning("Received notify message without valid credentials. Ignoring.");
|
||||
continue;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((size_t) n >= sizeof(buf)) {
|
||||
log_warning("Received notify message exceeded maximum size. Ignoring.");
|
||||
continue;
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf[n] = 0;
|
||||
@ -1615,7 +1614,6 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
|
||||
|
||||
if (fdset_size(fds) > 0)
|
||||
log_warning("Got auxiliary fds with notification message, closing all.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user