[newlib-cygwin/cygwin-3_6-branch] newlib: copy args for atexit()'ed function before unlock the mutex

Takashi Yano tyan0@sourceware.org
Thu Dec 4 10:00:52 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=23378fb147e85f572a493f13fe15fe47c764350b

commit 23378fb147e85f572a493f13fe15fe47c764350b
Author: Takashi Yano <takashi.yano@nifty.ne.jp>
Date:   Sat Nov 29 21:05:02 2025 +0900

    newlib: copy args for atexit()'ed function before unlock the mutex
    
    The commit a2a8bc771f2f has a problem that __atexit which includes
    args for atexit()'ed function may be touched by another thread
    since the mutex is unlocked while calling the function.
    With this path, the args, etc. are copyed to local variable to
    prevent this problem.
    
    Fixes: a2a8bc771f2f ("newlib: Unlock the mutex while calling atexit()'ed functions")
    Suggested-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
    Reviewed-by: Corinna Vinschen <corinna@vinschen.de>, Sebastian Huber <sebastian.huber@embedded-brains.de>
    Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
    (cherry picked from commit 7c7d9cf585d0d7c905f600eff14bf4f4e07fb178)

Diff:
---
 newlib/libc/stdlib/__call_atexit.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/newlib/libc/stdlib/__call_atexit.c b/newlib/libc/stdlib/__call_atexit.c
index 44f1f6acc..15ecda343 100644
--- a/newlib/libc/stdlib/__call_atexit.c
+++ b/newlib/libc/stdlib/__call_atexit.c
@@ -93,6 +93,8 @@ __call_exitprocs (int code, void *d)
       for (n = p->_ind - 1; n >= 0; n--)
 	{
 	  int ind;
+	  __ULong fntypes, is_cxa;
+	  void *fnarg;
 
 	  i = 1 << n;
 
@@ -114,18 +116,22 @@ __call_exitprocs (int code, void *d)
 
 	  ind = p->_ind;
 
+	  fntypes = args->_fntypes;
+	  is_cxa = args->_is_cxa;
+	  fnarg = args->_fnargs[n];
+
 #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)
+	  if (!args || (fntypes & i) == 0)
 	    fn ();
-	  else if ((args->_is_cxa & i) == 0)
-	    (*((void (*)(int, void *)) fn))(code, args->_fnargs[n]);
+	  else if ((is_cxa & i) == 0)
+	    (*((void (*)(int, void *)) fn))(code, fnarg);
 	  else
-	    (*((void (*)(void *)) fn))(args->_fnargs[n]);
+	    (*((void (*)(void *)) fn))(fnarg);
 #ifndef __SINGLE_THREAD__
 	  __lock_acquire_recursive(__atexit_recursive_mutex);
 #endif


More information about the Newlib-cvs mailing list