Skip to content

Commit a2a8bc7

Browse files
committed
newlib: Unlock the mutex while calling atexit()'ed functions
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: Corinna Vinschen <[email protected]> Signed-off-by: Takashi Yano <[email protected]>
1 parent d77cb8e commit a2a8bc7

File tree

1 file changed

+8
-0
lines changed

1 file changed

+8
-0
lines changed

newlib/libc/stdlib/__call_atexit.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,21 @@ __call_exitprocs (int code, void *d)
114114

115115
ind = p->_ind;
116116

117+
#ifndef __SINGLE_THREAD__
118+
/* Unlock __atexit_recursive_mutex; otherwise, the function fn() may
119+
deadlock if it waits for another thread which calls atexit(). */
120+
__lock_release_recursive(__atexit_recursive_mutex);
121+
#endif
117122
/* Call the function. */
118123
if (!args || (args->_fntypes & i) == 0)
119124
fn ();
120125
else if ((args->_is_cxa & i) == 0)
121126
(*((void (*)(int, void *)) fn))(code, args->_fnargs[n]);
122127
else
123128
(*((void (*)(void *)) fn))(args->_fnargs[n]);
129+
#ifndef __SINGLE_THREAD__
130+
__lock_acquire_recursive(__atexit_recursive_mutex);
131+
#endif
124132

125133
/* The function we called call atexit and registered another
126134
function (or functions). Call these new functions before

0 commit comments

Comments
 (0)