+static int manager_process_notify_fd(Manager *m) {
+ ssize_t n;
+
+ assert(m);
+
+ for (;;) {
+ char buf[4096];
+ struct msghdr msghdr;
+ struct iovec iovec;
+ struct ucred *ucred;
+ union {
+ struct cmsghdr cmsghdr;
+ uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
+ } control;
+ Unit *u;
+ char **tags;
+
+ zero(iovec);
+ iovec.iov_base = buf;
+ iovec.iov_len = sizeof(buf)-1;
+
+ zero(control);
+ zero(msghdr);
+ msghdr.msg_iov = &iovec;
+ msghdr.msg_iovlen = 1;
+ msghdr.msg_control = &control;
+ msghdr.msg_controllen = sizeof(control);
+
+ if ((n = recvmsg(m->notify_watch.fd, &msghdr, MSG_DONTWAIT)) <= 0) {
+ if (n >= 0)
+ return -EIO;
+
+ if (errno == EAGAIN)
+ break;
+
+ return -errno;
+ }
+
+ if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
+ control.cmsghdr.cmsg_level != SOL_SOCKET ||
+ control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
+ control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
+ log_warning("Received notify message without credentials. Ignoring.");
+ continue;
+ }
+
+ ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
+
+ if (!(u = hashmap_get(m->watch_pids, UINT32_TO_PTR(ucred->pid))))
+ if (!(u = cgroup_unit_by_pid(m, ucred->pid))) {
+ log_warning("Cannot find unit for notify message of PID %lu.", (unsigned long) ucred->pid);
+ continue;
+ }
+
+ assert((size_t) n < sizeof(buf));
+ buf[n] = 0;
+ if (!(tags = strv_split(buf, "\n\r")))
+ return -ENOMEM;
+
+ log_debug("Got notification message for unit %s", u->meta.id);
+
+ if (UNIT_VTABLE(u)->notify_message)
+ UNIT_VTABLE(u)->notify_message(u, ucred->pid, tags);
+
+ strv_free(tags);
+ }
+
+ return 0;
+}
+