dryang / rpms / systemd

Forked from rpms/systemd a year ago
Clone
923a60
From 6d1ef1fb841a0b3b4c53b560892f3570b3379dc9 Mon Sep 17 00:00:00 2001
923a60
From: Lennart Poettering <lennart@poettering.net>
923a60
Date: Wed, 10 Jun 2015 19:24:58 +0200
923a60
Subject: [PATCH] journald: don't employ inner loop for reading from incoming
923a60
 sockets
923a60
923a60
Otherwise, if the socket is constantly busy we will never return to the
923a60
event loop, but we really need to to dispatch other (possibly more
923a60
high-priority) events too. Hence, return after dispatching one message
923a60
to the event handler, and rely on the event loop calling us back
923a60
right-away.
923a60
923a60
Fixes #125
923a60
923a60
Related: #1318994
923a60
Cherry-picked from: a315ac4e076c4ce7ce3e5c95792cf916d5e918c5
923a60
---
923a60
 src/journal/journald-server.c | 204 +++++++++++++++++-----------------
923a60
 1 file changed, 100 insertions(+), 104 deletions(-)
923a60
923a60
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
923a60
index 1eb1394d10..275224dc99 100644
923a60
--- a/src/journal/journald-server.c
923a60
+++ b/src/journal/journald-server.c
923a60
@@ -1103,6 +1103,42 @@ finish:
923a60
 
923a60
 int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
923a60
         Server *s = userdata;
923a60
+        struct ucred *ucred = NULL;
923a60
+        struct timeval *tv = NULL;
923a60
+        struct cmsghdr *cmsg;
923a60
+        char *label = NULL;
923a60
+        size_t label_len = 0, m;
923a60
+        struct iovec iovec;
923a60
+        ssize_t n;
923a60
+        int *fds = NULL, v = 0;
923a60
+        unsigned n_fds = 0;
923a60
+
923a60
+        union {
923a60
+                struct cmsghdr cmsghdr;
923a60
+
923a60
+                /* We use NAME_MAX space for the SELinux label
923a60
+                 * here. The kernel currently enforces no
923a60
+                 * limit, but according to suggestions from
923a60
+                 * the SELinux people this will change and it
923a60
+                 * will probably be identical to NAME_MAX. For
923a60
+                 * now we use that, but this should be updated
923a60
+                 * one day when the final limit is known. */
923a60
+                uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
923a60
+                            CMSG_SPACE(sizeof(struct timeval)) +
923a60
+                            CMSG_SPACE(sizeof(int)) + /* fd */
923a60
+                            CMSG_SPACE(NAME_MAX)]; /* selinux label */
923a60
+        } control = {};
923a60
+
923a60
+        union sockaddr_union sa = {};
923a60
+
923a60
+        struct msghdr msghdr = {
923a60
+                .msg_iov = &iovec,
923a60
+                .msg_iovlen = 1,
923a60
+                .msg_control = &control,
923a60
+                .msg_controllen = sizeof(control),
923a60
+                .msg_name = &sa,
923a60
+                .msg_namelen = sizeof(sa),
923a60
+        };
923a60
 
923a60
         assert(s);
923a60
         assert(fd == s->native_fd || fd == s->syslog_fd || fd == s->audit_fd);
923a60
@@ -1112,119 +1148,79 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
923a60
                 return -EIO;
923a60
         }
923a60
 
923a60
-        for (;;) {
923a60
-                struct ucred *ucred = NULL;
923a60
-                struct timeval *tv = NULL;
923a60
-                struct cmsghdr *cmsg;
923a60
-                char *label = NULL;
923a60
-                size_t label_len = 0;
923a60
-                struct iovec iovec;
923a60
-
923a60
-                union {
923a60
-                        struct cmsghdr cmsghdr;
923a60
-
923a60
-                        /* We use NAME_MAX space for the SELinux label
923a60
-                         * here. The kernel currently enforces no
923a60
-                         * limit, but according to suggestions from
923a60
-                         * the SELinux people this will change and it
923a60
-                         * will probably be identical to NAME_MAX. For
923a60
-                         * now we use that, but this should be updated
923a60
-                         * one day when the final limit is known. */
923a60
-                        uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
923a60
-                                    CMSG_SPACE(sizeof(struct timeval)) +
923a60
-                                    CMSG_SPACE(sizeof(int)) + /* fd */
923a60
-                                    CMSG_SPACE(NAME_MAX)]; /* selinux label */
923a60
-                } control = {};
923a60
-                union sockaddr_union sa = {};
923a60
-                struct msghdr msghdr = {
923a60
-                        .msg_iov = &iovec,
923a60
-                        .msg_iovlen = 1,
923a60
-                        .msg_control = &control,
923a60
-                        .msg_controllen = sizeof(control),
923a60
-                        .msg_name = &sa,
923a60
-                        .msg_namelen = sizeof(sa),
923a60
-                };
923a60
-
923a60
-                ssize_t n;
923a60
-                int *fds = NULL;
923a60
-                unsigned n_fds = 0;
923a60
-                int v = 0;
923a60
-                size_t m;
923a60
-
923a60
-                /* Try to get the right size, if we can. (Not all
923a60
-                 * sockets support SIOCINQ, hence we just try, but
923a60
-                 * don't rely on it. */
923a60
-                (void) ioctl(fd, SIOCINQ, &v);
923a60
-
923a60
-                /* Fix it up, if it is too small. We use the same fixed value as auditd here. Awful! */
923a60
-                m = PAGE_ALIGN(MAX3((size_t) v + 1,
923a60
-                                    (size_t) LINE_MAX,
923a60
-                                    ALIGN(sizeof(struct nlmsghdr)) + ALIGN((size_t) MAX_AUDIT_MESSAGE_LENGTH)) + 1);
923a60
-
923a60
-                if (!GREEDY_REALLOC(s->buffer, s->buffer_size, m))
923a60
-                        return log_oom();
923a60
-
923a60
-                iovec.iov_base = s->buffer;
923a60
-                iovec.iov_len = s->buffer_size - 1; /* Leave room for trailing NUL we add later */
923a60
-
923a60
-                n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
923a60
-                if (n < 0) {
923a60
-                        if (errno == EINTR || errno == EAGAIN)
923a60
-                                return 0;
923a60
-
923a60
-                        log_error_errno(errno, "recvmsg() failed: %m");
923a60
-                        return -errno;
923a60
-                }
923a60
+        /* Try to get the right size, if we can. (Not all
923a60
+         * sockets support SIOCINQ, hence we just try, but
923a60
+         * don't rely on it. */
923a60
+        (void) ioctl(fd, SIOCINQ, &v);
923a60
 
923a60
-                CMSG_FOREACH(cmsg, &msghdr) {
923a60
-
923a60
-                        if (cmsg->cmsg_level == SOL_SOCKET &&
923a60
-                            cmsg->cmsg_type == SCM_CREDENTIALS &&
923a60
-                            cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
923a60
-                                ucred = (struct ucred*) CMSG_DATA(cmsg);
923a60
-                        else if (cmsg->cmsg_level == SOL_SOCKET &&
923a60
-                                 cmsg->cmsg_type == SCM_SECURITY) {
923a60
-                                label = (char*) CMSG_DATA(cmsg);
923a60
-                                label_len = cmsg->cmsg_len - CMSG_LEN(0);
923a60
-                        } else if (cmsg->cmsg_level == SOL_SOCKET &&
923a60
-                                   cmsg->cmsg_type == SO_TIMESTAMP &&
923a60
-                                   cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
923a60
-                                tv = (struct timeval*) CMSG_DATA(cmsg);
923a60
-                        else if (cmsg->cmsg_level == SOL_SOCKET &&
923a60
-                                 cmsg->cmsg_type == SCM_RIGHTS) {
923a60
-                                fds = (int*) CMSG_DATA(cmsg);
923a60
-                                n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
923a60
-                        }
923a60
-                }
923a60
+        /* Fix it up, if it is too small. We use the same fixed value as auditd here. Awful! */
923a60
+        m = PAGE_ALIGN(MAX3((size_t) v + 1,
923a60
+                            (size_t) LINE_MAX,
923a60
+                            ALIGN(sizeof(struct nlmsghdr)) + ALIGN((size_t) MAX_AUDIT_MESSAGE_LENGTH)) + 1);
923a60
 
923a60
-                /* And a trailing NUL, just in case */
923a60
-                s->buffer[n] = 0;
923a60
+        if (!GREEDY_REALLOC(s->buffer, s->buffer_size, m))
923a60
+                return log_oom();
923a60
 
923a60
-                if (fd == s->syslog_fd) {
923a60
-                        if (n > 0 && n_fds == 0)
923a60
-                                server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
923a60
-                        else if (n_fds > 0)
923a60
-                                log_warning("Got file descriptors via syslog socket. Ignoring.");
923a60
+        iovec.iov_base = s->buffer;
923a60
+        iovec.iov_len = s->buffer_size - 1; /* Leave room for trailing NUL we add later */
923a60
 
923a60
-                } else if (fd == s->native_fd) {
923a60
-                        if (n > 0 && n_fds == 0)
923a60
-                                server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len);
923a60
-                        else if (n == 0 && n_fds == 1)
923a60
-                                server_process_native_file(s, fds[0], ucred, tv, label, label_len);
923a60
-                        else if (n_fds > 0)
923a60
-                                log_warning("Got too many file descriptors via native socket. Ignoring.");
923a60
+        n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
923a60
+        if (n < 0) {
923a60
+                if (errno == EINTR || errno == EAGAIN)
923a60
+                        return 0;
923a60
 
923a60
-                } else {
923a60
-                        assert(fd == s->audit_fd);
923a60
+                return log_error_errno(errno, "recvmsg() failed: %m");
923a60
+        }
923a60
 
923a60
-                        if (n > 0 && n_fds == 0)
923a60
-                                server_process_audit_message(s, s->buffer, n, ucred, &sa, msghdr.msg_namelen);
923a60
-                        else if (n_fds > 0)
923a60
-                                log_warning("Got file descriptors via audit socket. Ignoring.");
923a60
+        CMSG_FOREACH(cmsg, &msghdr) {
923a60
+
923a60
+                if (cmsg->cmsg_level == SOL_SOCKET &&
923a60
+                    cmsg->cmsg_type == SCM_CREDENTIALS &&
923a60
+                    cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
923a60
+                        ucred = (struct ucred*) CMSG_DATA(cmsg);
923a60
+                else if (cmsg->cmsg_level == SOL_SOCKET &&
923a60
+                         cmsg->cmsg_type == SCM_SECURITY) {
923a60
+                        label = (char*) CMSG_DATA(cmsg);
923a60
+                        label_len = cmsg->cmsg_len - CMSG_LEN(0);
923a60
+                } else if (cmsg->cmsg_level == SOL_SOCKET &&
923a60
+                           cmsg->cmsg_type == SO_TIMESTAMP &&
923a60
+                           cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
923a60
+                        tv = (struct timeval*) CMSG_DATA(cmsg);
923a60
+                else if (cmsg->cmsg_level == SOL_SOCKET &&
923a60
+                         cmsg->cmsg_type == SCM_RIGHTS) {
923a60
+                        fds = (int*) CMSG_DATA(cmsg);
923a60
+                        n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
923a60
                 }
923a60
+        }
923a60
+
923a60
+        /* And a trailing NUL, just in case */
923a60
+        s->buffer[n] = 0;
923a60
+
923a60
+        if (fd == s->syslog_fd) {
923a60
+                if (n > 0 && n_fds == 0)
923a60
+                        server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
923a60
+                else if (n_fds > 0)
923a60
+                        log_warning("Got file descriptors via syslog socket. Ignoring.");
923a60
+
923a60
+        } else if (fd == s->native_fd) {
923a60
+                if (n > 0 && n_fds == 0)
923a60
+                        server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len);
923a60
+                else if (n == 0 && n_fds == 1)
923a60
+                        server_process_native_file(s, fds[0], ucred, tv, label, label_len);
923a60
+                else if (n_fds > 0)
923a60
+                        log_warning("Got too many file descriptors via native socket. Ignoring.");
923a60
 
923a60
-                close_many(fds, n_fds);
923a60
+        } else {
923a60
+                assert(fd == s->audit_fd);
923a60
+
923a60
+                if (n > 0 && n_fds == 0)
923a60
+                        server_process_audit_message(s, s->buffer, n, ucred, &sa, msghdr.msg_namelen);
923a60
+                else if (n_fds > 0)
923a60
+                        log_warning("Got file descriptors via audit socket. Ignoring.");
923a60
         }
923a60
+
923a60
+        close_many(fds, n_fds);
923a60
+        return 0;
923a60
 }
923a60
 
923a60
 static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {