- add field to transient units that indicate whether systemd or somebody else saves/restores its settings, for integration with libvirt
- ensure scope units may be started only a single time
-* switch to SipHash for hashmaps/sets?
+* code cleanup
+ - get rid of readdir_r/dirent_storage stuff, it's unnecessary on Linux
+ - we probably should replace the left-over uses of strv_append() and replace them by strv_push() or strv_extend()
-* general: get rid of readdir_r/dirent_storage stuff, it's unnecessary on Linux
+* switch to SipHash for hashmaps/sets?
* when we detect low battery and no AC on boot, show pretty splash and refuse boot
* Add a new Distribute=$NUMBER key to socket units that makes use of SO_REUSEPORT to distribute network traffic on $NUMBER instances
-* we probably should replace the left-over uses of strv_append() and replace them by strv_push() or strv_extend()
-
* move config_parse_path_strv() out of conf-parser.c
* After coming back from hibernation reset hibernation swap partition using the /dev/snapshot ioctl APIs
but do not return anything up to the event loop caller. Instead
add parameter to sd_event_request_quit() to take retval. This way
errors rippling upwards are the option, not the default
- - child pid handling: first invoke waitid(WNOHANG) and call event handler, only afterwards reap the process
- native support for watchdog stuff
* in the final killing spree, detect processes from the root directory, and
don't care about. Since this is O(n) this means that if you
have a lot of processes you probably want to handle SIGCHLD
yourself.
+
+ We do not reap the children here (by using WNOWAIT), this
+ is only done after the event source is dispatched so that
+ the callback still sees the process as a zombie.
*/
HASHMAP_FOREACH(s, e->child_sources, i) {
continue;
zero(s->child.siginfo);
- r = waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|s->child.options);
+ r = waitid(P_PID, s->child.pid, &s->child.siginfo,
+ WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options);
if (r < 0)
return -errno;
if (s->child.siginfo.si_pid != 0) {
+ bool zombie =
+ s->child.siginfo.si_code == CLD_EXITED ||
+ s->child.siginfo.si_code == CLD_KILLED ||
+ s->child.siginfo.si_code == CLD_DUMPED;
+
+ if (!zombie && (s->child.options & WEXITED)) {
+ /* If the child isn't dead then let's
+ * immediately remove the state change
+ * from the queue, since there's no
+ * benefit in leaving it queued */
+
+ assert(s->child.options & (WSTOPPED|WCONTINUED));
+ waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|(s->child.options & (WSTOPPED|WCONTINUED)));
+ }
+
r = source_set_pending(s, true);
if (r < 0)
return r;
return r;
}
-
return 0;
}
r = s->signal.callback(s, &s->signal.siginfo, s->userdata);
break;
- case SOURCE_CHILD:
+ case SOURCE_CHILD: {
+ bool zombie;
+
+ zombie = s->child.siginfo.si_code == CLD_EXITED ||
+ s->child.siginfo.si_code == CLD_KILLED ||
+ s->child.siginfo.si_code == CLD_DUMPED;
+
r = s->child.callback(s, &s->child.siginfo, s->userdata);
+
+ /* Now, reap the PID for good. */
+ if (zombie)
+ waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED);
+
break;
+ }
case SOURCE_DEFER:
r = s->defer.callback(s, s->userdata);