Module Name: src
Committed By: riastradh
Date: Sat Mar 15 12:11:09 UTC 2025
Modified Files:
src/sys/kern: kern_exec.c
Log Message:
posix_spawn(2): Fix race between parent and child.
This was an embarrassing misuse of condition variables.
PR kern/59175: posix_spawn hang, hanging other process too
PR kern/52634: possible unhandled spurious wakeup in posix_spawn
(This only resolves one of the symptoms wiz had in PR 59175; there is
also another issue involved with p_vmspace and p_psstrp.)
To generate a diff of this commit:
cvs rdiff -u -r1.525 -r1.526 src/sys/kern/kern_exec.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/kern_exec.c
diff -u src/sys/kern/kern_exec.c:1.525 src/sys/kern/kern_exec.c:1.526
--- src/sys/kern/kern_exec.c:1.525 Fri Dec 6 16:48:13 2024
+++ src/sys/kern/kern_exec.c Sat Mar 15 12:11:09 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_exec.c,v 1.525 2024/12/06 16:48:13 riastradh Exp $ */
+/* $NetBSD: kern_exec.c,v 1.526 2025/03/15 12:11:09 riastradh Exp $ */
/*-
* Copyright (c) 2008, 2019, 2020 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.525 2024/12/06 16:48:13 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.526 2025/03/15 12:11:09 riastradh Exp $");
#include "opt_exec.h"
#include "opt_execfmt.h"
@@ -281,6 +281,7 @@ struct spawn_exec_data {
kcondvar_t sed_cv_child_ready;
kmutex_t sed_mtx_child;
int sed_error;
+ bool sed_child_ready;
volatile uint32_t sed_refcnt;
};
@@ -2347,6 +2348,9 @@ spawn_return(void *arg)
&& rw_tryenter(&exec_lock, RW_READER)) {
parent_is_waiting = false;
mutex_enter(&spawn_data->sed_mtx_child);
+ KASSERT(!spawn_data->sed_child_ready);
+ spawn_data->sed_error = 0;
+ spawn_data->sed_child_ready = true;
cv_signal(&spawn_data->sed_cv_child_ready);
mutex_exit(&spawn_data->sed_mtx_child);
}
@@ -2376,6 +2380,9 @@ spawn_return(void *arg)
if (parent_is_waiting) {
mutex_enter(&spawn_data->sed_mtx_child);
+ KASSERT(!spawn_data->sed_child_ready);
+ spawn_data->sed_error = 0;
+ spawn_data->sed_child_ready = true;
cv_signal(&spawn_data->sed_cv_child_ready);
mutex_exit(&spawn_data->sed_mtx_child);
}
@@ -2409,7 +2416,9 @@ spawn_return(void *arg)
if (parent_is_waiting) {
/* pass error to parent */
mutex_enter(&spawn_data->sed_mtx_child);
+ KASSERT(!spawn_data->sed_child_ready);
spawn_data->sed_error = error;
+ spawn_data->sed_child_ready = true;
cv_signal(&spawn_data->sed_cv_child_ready);
mutex_exit(&spawn_data->sed_mtx_child);
} else {
@@ -2814,7 +2823,10 @@ do_posix_spawn(struct lwp *l1, pid_t *pi
mutex_exit(p2->p_lock);
mutex_exit(&proc_lock);
- cv_wait(&spawn_data->sed_cv_child_ready, &spawn_data->sed_mtx_child);
+ while (!spawn_data->sed_child_ready) {
+ cv_wait(&spawn_data->sed_cv_child_ready,
+ &spawn_data->sed_mtx_child);
+ }
error = spawn_data->sed_error;
mutex_exit(&spawn_data->sed_mtx_child);
spawn_exec_data_release(spawn_data);