mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-10 01:17:44 +03:00
event: when handling SIGCHLD of a child process only reap after dispatching event source
That way the even source callback is run with the zombie process still around so that it can access /proc/$PID/ and similar, and so that it can be sure that the PID has not been reused yet.
This commit is contained in:
parent
e599ba01f5
commit
08cd155254
9
TODO
9
TODO
@ -45,9 +45,11 @@ Features:
|
||||
- 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
|
||||
|
||||
@ -71,8 +73,6 @@ Features:
|
||||
|
||||
* 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
|
||||
@ -137,7 +137,6 @@ Features:
|
||||
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
|
||||
|
@ -1555,6 +1555,10 @@ static int process_child(sd_event *e) {
|
||||
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) {
|
||||
@ -1567,11 +1571,27 @@ static int process_child(sd_event *e) {
|
||||
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;
|
||||
@ -1625,7 +1645,6 @@ static int process_signal(sd_event *e, uint32_t events) {
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1667,9 +1686,21 @@ static int source_dispatch(sd_event_source *s) {
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user