Skip to content

Commit 8fd6535

Browse files
nabijaczlewelibehlendorf
authored andcommitted
zed: protect against wait4()/fork() races to the launched process tree
As soon as wait4() returns, fork() can immediately return with the same PID, and race to lock _launched_processes_lock, then try to add the new (duplicate) PID to _launched_processes, which asserts By locking before wait4(), we ensure, that, given that same unfortunate scheduling, _launched_processes_lock cannot be locked by the spawner before we pop the process in the reaper, and only afterward will it be added This moves where the reaper idles when there are children from the wait4() to the pause(), locking for the duration of that single syscall in both the no-children and running-children cases; the impact of this is one to two syscalls (depending on _launched_processes_lock state) per loop Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Don Brady <[email protected]> Signed-off-by: Ahelenia Ziemiańska <[email protected]> Closes #11924 Closes #11928
1 parent 79d9f66 commit 8fd6535

File tree

1 file changed

+5
-4
lines changed

1 file changed

+5
-4
lines changed

cmd/zed/zed_exec.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,12 @@ _reap_children(void *arg)
205205
(void) sigaction(SIGCHLD, &sa, NULL);
206206

207207
for (_reap_children_stop = B_FALSE; !_reap_children_stop; ) {
208-
pid = wait4(0, &status, 0, &usage);
208+
(void) pthread_mutex_lock(&_launched_processes_lock);
209+
pid = wait4(0, &status, WNOHANG, &usage);
209210

210-
if (pid == (pid_t)-1) {
211-
if (errno == ECHILD)
211+
if (pid == 0 || pid == (pid_t)-1) {
212+
(void) pthread_mutex_unlock(&_launched_processes_lock);
213+
if (pid == 0 || errno == ECHILD)
212214
pause();
213215
else if (errno != EINTR)
214216
zed_log_msg(LOG_WARNING,
@@ -217,7 +219,6 @@ _reap_children(void *arg)
217219
} else {
218220
memset(&node, 0, sizeof (node));
219221
node.pid = pid;
220-
(void) pthread_mutex_lock(&_launched_processes_lock);
221222
pnode = avl_find(&_launched_processes, &node, NULL);
222223
if (pnode) {
223224
memcpy(&node, pnode, sizeof (node));

0 commit comments

Comments
 (0)