[PATCH] newlib: Unlock the mutex while calling atexit()'ed functions

Takashi Yano <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
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 <[email protected]>
Reviewed-by:
Signed-off-by: Takashi Yano <[email protected]>
---
 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.