diff options
| author | Arjun Shankar <arjun@redhat.com> | 2024-10-18 16:03:25 +0200 |
|---|---|---|
| committer | Arjun Shankar <arjun@redhat.com> | 2024-10-23 13:40:16 +0200 |
| commit | 9f0d2c0ee6c728643fcf9a4879e9f20f5e45ce5f (patch) | |
| tree | 86cff8d63944f5a0e573b1d0a72d3a669c4f124d /posix | |
| parent | 81439a116cf48583127ddf1f09809440aa40969a (diff) | |
libio: Fix a deadlock after fork in popen
popen modifies its file handler book-keeping under a lock that wasn't
being taken during fork. This meant that a concurrent popen and fork
could end up copying the lock in a "locked" state into the fork child,
where subsequently calling popen would lead to a deadlock due to the
already (spuriously) held lock.
This commit fixes the deadlock by appropriately taking the lock before
fork, and releasing/resetting it in the parent/child after the fork.
A new test for concurrent popen and fork is also added. It consistently
hangs (and therefore fails via timeout) without the fix applied.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
Diffstat (limited to 'posix')
| -rw-r--r-- | posix/fork.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/posix/fork.c b/posix/fork.c index c2b476ff2d..bd6371a9f4 100644 --- a/posix/fork.c +++ b/posix/fork.c @@ -62,6 +62,7 @@ __libc_fork (void) call_function_static_weak (__nss_database_fork_prepare_parent, &nss_database_data); + _IO_proc_file_chain_lock (); _IO_list_lock (); /* Acquire malloc locks. This needs to come last because fork @@ -94,6 +95,7 @@ __libc_fork (void) /* Reset locks in the I/O code. */ _IO_list_resetlock (); + _IO_proc_file_chain_resetlock (); call_function_static_weak (__nss_database_fork_subprocess, &nss_database_data); @@ -123,6 +125,7 @@ __libc_fork (void) /* We execute this even if the 'fork' call failed. */ _IO_list_unlock (); + _IO_proc_file_chain_unlock (); } /* Run the handlers registered for the parent. */ |
