[PATCH] newlib: Unlock the mutex while calling atexit()'ed functions
Takashi Yano
takashi.yano@nifty.ne.jp
Tue Nov 18 13:31:33 GMT 2025
The atexit()'ed function may deadlock if it waits for another thread
which calls atexit() in the current __call_atexit.c code. This patch
unlock __atexit_recursive_mutex while calling atexit()'ed functions
to avoid the deadlock mentioned above. glibc and Darwin do the same,
so it sounds reasonable.
Addresses: https://cygwin.com/pipermail/cygwin/2025-October/258930.html
Reported-by: Tomohiro Kashiwada <tomohiro-kashiwada@ezweb.ne.jp>
Reviewed-by:
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
---
newlib/libc/stdlib/__call_atexit.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/newlib/libc/stdlib/__call_atexit.c b/newlib/libc/stdlib/__call_atexit.c
index 710440389..44f1f6acc 100644
--- a/newlib/libc/stdlib/__call_atexit.c
+++ b/newlib/libc/stdlib/__call_atexit.c
@@ -114,6 +114,11 @@ __call_exitprocs (int code, void *d)
ind = p->_ind;
+#ifndef __SINGLE_THREAD__
+ /* Unlock __atexit_recursive_mutex; otherwise, the function fn() may
+ deadlock if it waits for another thread which calls atexit(). */
+ __lock_release_recursive(__atexit_recursive_mutex);
+#endif
/* Call the function. */
if (!args || (args->_fntypes & i) == 0)
fn ();
@@ -121,6 +126,9 @@ __call_exitprocs (int code, void *d)
(*((void (*)(int, void *)) fn))(code, args->_fnargs[n]);
else
(*((void (*)(void *)) fn))(args->_fnargs[n]);
+#ifndef __SINGLE_THREAD__
+ __lock_acquire_recursive(__atexit_recursive_mutex);
+#endif
/* The function we called call atexit and registered another
function (or functions). Call these new functions before
--
2.51.0
More information about the Newlib
mailing list