| Message ID | 20251118133140.78-1-takashi.yano@nifty.ne.jp |
|---|---|
| State | New |
| Headers |
Return-Path: <newlib-bounces~patchwork=sourceware.org@sourceware.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 0A1E03857003 for <patchwork@sourceware.org>; Tue, 18 Nov 2025 13:32:43 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0A1E03857003 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=nifty.ne.jp header.i=@nifty.ne.jp header.a=rsa-sha256 header.s=default-1th84yt82rvi header.b=etXmijbC X-Original-To: newlib@sourceware.org Delivered-To: newlib@sourceware.org Received: from mta-snd-w07.mail.nifty.com (mta-snd-w07.mail.nifty.com [IPv6:2001:268:fa30:831:6a:99:e3:27]) by sourceware.org (Postfix) with ESMTPS id DA23C3858CD9 for <newlib@sourceware.org>; Tue, 18 Nov 2025 13:31:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DA23C3858CD9 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=nifty.ne.jp Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nifty.ne.jp ARC-Filter: OpenARC Filter v1.0.0 sourceware.org DA23C3858CD9 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2001:268:fa30:831:6a:99:e3:27 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1763472712; cv=none; b=fJKHBNYQ6AQWnkcrQpG/RdFCp4uMhE6IjMG6XS0uCAQQ7PrSOwS/WtI4Y9Wu0sLR29lqsQZoadCYYS60DxvVNnnb3gr49jmpj+z/SUV77u+sLo+mD+bkg7t4JWiI/73bA4Ncv1YLX7SK1Ubqn27J5c2rZwhnrmdoFZYGpc4d5Mk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1763472712; c=relaxed/simple; bh=EXQUjeRg6tPqBBI1kjnHsaYHh+n22olDHgSbUYSSTTM=; h=From:To:Subject:Date:Message-ID:MIME-Version:DKIM-Signature; b=dtHM1+ZwOXoDXrdj0TVm9JTFYqU3ABEdET+gfDQVYIKbWUU8PkoU3rjvDqHUDhCj0yDZ4bYJ3otWvp2hMd0SUHwinWCmMbcutSgojgumjrkVDWya/TSPXSWZEynsHfr1AcufeVvKC3B916BjUdI/Hw5aq3WcDX+SFGHGYLDOQ6Y= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DA23C3858CD9 Received: from HP-Z230 by mta-snd-w07.mail.nifty.com with ESMTP id <20251118133150205.KUMP.19957.HP-Z230@nifty.com>; Tue, 18 Nov 2025 22:31:50 +0900 From: Takashi Yano <takashi.yano@nifty.ne.jp> To: newlib@sourceware.org Cc: Takashi Yano <takashi.yano@nifty.ne.jp>, Tomohiro Kashiwada <tomohiro-kashiwada@ezweb.ne.jp> Subject: [PATCH] newlib: Unlock the mutex while calling atexit()'ed functions Date: Tue, 18 Nov 2025 22:31:33 +0900 Message-ID: <20251118133140.78-1-takashi.yano@nifty.ne.jp> X-Mailer: git-send-email 2.51.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.ne.jp; s=default-1th84yt82rvi; t=1763472710; bh=/awL8EgvjuLynG4f/gJv0rx+u+qIuqyCEhMsx1BzhV0=; h=From:To:Cc:Subject:Date; b=etXmijbCS1ObWJ2O+mQKmU4l6q+GWoAQygrAlQMbDphZqKpMlUKcP8zSVGogICsXJtqv8dFU 99JA+a1KsIHaiFjp4jHmk+5IoIY7wMjGrfa4nJ3PfV9ggtXe3NQ+3Vs807g1mnKELQrAAmG2cM ytxAInjwOGcYzxtRV3spJuJ8GpDPIzIDTX3DuEaxzv9XLBc7Bga5cE+q8V4jzLvmJThO4j4dyA oW18+U8lXiB8HOw4nfW73XEpfFePlu5cCrBzwspRIBesQn3XfqykrjTqCjdEYwU/UsfoKC72Do DYa489gUsDT0vWUjrFEn8piShqIFsIKpDhex6NM/hsZsVtYQ== X-Spam-Status: No, score=-10.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: newlib@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Newlib mailing list <newlib.sourceware.org> List-Unsubscribe: <https://sourceware.org/mailman/options/newlib>, <mailto:newlib-request@sourceware.org?subject=unsubscribe> List-Archive: <https://sourceware.org/pipermail/newlib/> List-Post: <mailto:newlib@sourceware.org> List-Help: <mailto:newlib-request@sourceware.org?subject=help> List-Subscribe: <https://sourceware.org/mailman/listinfo/newlib>, <mailto:newlib-request@sourceware.org?subject=subscribe> Errors-To: newlib-bounces~patchwork=sourceware.org@sourceware.org |
| Series |
newlib: Unlock the mutex while calling atexit()'ed functions
|
|
Commit Message
Takashi Yano
Nov. 18, 2025, 1:31 p.m. UTC
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(+)
Comments
Hi Takashi, On Nov 18 22:31, Takashi Yano wrote: > 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 LGTM, please push. Thanks, Corinna
Hello Takashi Yano, I have some questions to the change. ----- Am 18. Nov 2025 um 14:31 schrieb Takashi Yano takashi.yano@nifty.ne.jp: > 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 Here, a potentially shared structure is used through the args pointer. If some other thread calls exit() or atexit() concurrently, then this could result in a use of altered or freed memory. The data of the structure referenced by args should be first copied to local variables. Also I think that the deallocation should be done before we release the lock. We probably also have to restart the process after each handler call unconditionally. > /* 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
Hi Takashi, Hi Sebastian, did you discuss this in PM, by any chance? Is there any difference in GLibc or Darwin which explains how this potential problem is fixed there? Thanks, Corinna On Nov 26 05:17, Sebastian Huber wrote: > Hello Takashi Yano, > > I have some questions to the change. > > ----- Am 18. Nov 2025 um 14:31 schrieb Takashi Yano takashi.yano@nifty.ne.jp: > > > 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 > > Here, a potentially shared structure is used through the args pointer. If some other thread calls exit() or atexit() concurrently, then this could result in a use of altered or freed memory. The data of the structure referenced by args should be first copied to local variables. Also I think that the deallocation should be done before we release the lock. We probably also have to restart the process after each handler call unconditionally. > > > > /* 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 > > -- > embedded brains GmbH & Co. KG > Herr Sebastian HUBER > Dornierstr. 4 > 82178 Puchheim > Germany > email: sebastian.huber@embedded-brains.de > phone: +49-89-18 94 741 - 16 > fax: +49-89-18 94 741 - 08 > > Registergericht: Amtsgericht München > Registernummer: HRB 157899 > Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler > Unsere Datenschutzerklärung finden Sie hier: > https://embedded-brains.de/datenschutzerklaerung/
Hi Corinna, Sebasitian, On Fri, 28 Nov 2025 13:21:35 +0100 Corinna Vinschen wrote: > Hi Takashi, Hi Sebastian, > > did you discuss this in PM, by any chance? Is there any difference in > GLibc or Darwin which explains how this potential problem is fixed > there? In glibc, the value of fnargs, etc is just copyied to local variable. So, I think the followign patch is also OK for newlib. 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 > On Nov 26 05:17, Sebastian Huber wrote: > > Hello Takashi Yano, > > > > I have some questions to the change. > > > > ----- Am 18. Nov 2025 um 14:31 schrieb Takashi Yano takashi.yano@nifty.ne.jp: > > > > > 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 > > > > Here, a potentially shared structure is used through the args pointer. If some other thread calls exit() or atexit() concurrently, then this could result in a use of altered or freed memory. The data of the structure referenced by args should be first copied to local variables. Also I think that the deallocation should be done before we release the lock. We probably also have to restart the process after each handler call unconditionally. Thanks for pointing this out. What do you think of the patch above? > > > /* 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
Comparing with GLibc, this looks right to me. Ok with you, Sebastian? Thanks, Corinna On Nov 29 20:38, Takashi Yano wrote: > Hi Corinna, Sebasitian, > > On Fri, 28 Nov 2025 13:21:35 +0100 > Corinna Vinschen wrote: > > Hi Takashi, Hi Sebastian, > > > > did you discuss this in PM, by any chance? Is there any difference in > > GLibc or Darwin which explains how this potential problem is fixed > > there? > > In glibc, the value of fnargs, etc is just copyied to local variable. > So, I think the followign patch is also OK for newlib. > > 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 > > > > On Nov 26 05:17, Sebastian Huber wrote: > > > Hello Takashi Yano, > > > > > > I have some questions to the change. > > > > > > ----- Am 18. Nov 2025 um 14:31 schrieb Takashi Yano takashi.yano@nifty.ne.jp: > > > > > > > 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 > > > > > > Here, a potentially shared structure is used through the args pointer. If some other thread calls exit() or atexit() concurrently, then this could result in a use of altered or freed memory. The data of the structure referenced by args should be first copied to local variables. Also I think that the deallocation should be done before we release the lock. We probably also have to restart the process after each handler call unconditionally. > > Thanks for pointing this out. > > What do you think of the patch above? > > > > > /* 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 > > -- > Takashi Yano <takashi.yano@nifty.ne.jp>
Hello,
----- Am 1. Dez 2025 um 17:48 schrieb Corinna Vinschen vinschen@redhat.com:
> Comparing with GLibc, this looks right to me. Ok with you, Sebastian?
yes, looks good, thanks.
There could be still some use after free issues, however, I would have to develop a test case for this to be sure.
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