+
+ /* FIXME... the list of jobs might have changed */
+ }
+}
+
+int manager_dispatch_sigchld(Manager *m) {
+ assert(m);
+
+ for (;;) {
+ siginfo_t si;
+ Name *n;
+
+ zero(si);
+ if (waitid(P_ALL, 0, &si, WNOHANG) < 0)
+ return -errno;
+
+ if (si.si_pid == 0)
+ break;
+
+ if (!(n = hashmap_remove(m->watch_pids, UINT32_TO_PTR(si.si_pid))))
+ continue;
+
+ NAME_VTABLE(n)->sigchld_event(n, si.si_pid, si.si_code, si.si_status);
+ }
+
+ return 0;
+}
+
+int manager_process_signal_fd(Manager *m) {
+ ssize_t n;
+ struct signalfd_siginfo sfsi;
+ bool sigchld = false;
+
+ assert(m);
+
+ for (;;) {
+ if ((n = read(m->signal_fd, &sfsi, sizeof(sfsi))) != sizeof(sfsi)) {
+
+ if (n >= 0)
+ return -EIO;
+
+ if (errno == EAGAIN)
+ return 0;
+
+ return -errno;
+ }
+
+ if (sfsi.ssi_signo == SIGCHLD)
+ sigchld = true;
+ }
+
+ if (sigchld)
+ manager_dispatch_sigchld(m);
+
+ return 0;
+}
+
+int manager_loop(Manager *m) {
+ int r;
+ struct epoll_event events[32];
+
+ assert(m);
+
+ for (;;) {
+ int n, i;
+
+ if ((n = epoll_wait(m->epoll_fd, events, ELEMENTSOF(events), -1)) < 0) {
+
+ if (errno == -EINTR)
+ continue;
+
+ return -errno;
+ }
+
+ for (i = 0; i < n; i++) {
+
+ if (events[i].data.fd == m->signal_fd) {
+
+ /* An incoming signal? */
+ if (events[i].events != POLLIN)
+ return -EINVAL;
+
+ if ((r = manager_process_signal_fd(m)) < 0)
+ return -r;
+ } else {
+ Name *n;
+
+ /* Some other fd event, to be dispatched to the names */
+ assert_se(n = events[i].data.ptr);
+ NAME_VTABLE(n)->fd_event(n, events[i].data.fd, events[i].events);
+ }
+ }