DMARC-Filter: OpenDMARC Filter v1.4.2 delorie.com 53A96JVu3180803 Authentication-Results: delorie.com; dmarc=pass (p=none dis=none) header.from=cygwin.com Authentication-Results: delorie.com; spf=pass smtp.mailfrom=cygwin.com DKIM-Filter: OpenDKIM Filter v2.11.0 delorie.com 53A96JVu3180803 Authentication-Results: delorie.com; dkim=pass (1024-bit key, unprotected) header.d=cygwin.com header.i=@cygwin.com header.a=rsa-sha256 header.s=default header.b=EjkanyEy X-Recipient: archive-cygwin AT delorie DOT com DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B3A013839821 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cygwin.com; s=default; t=1744275978; bh=HRKAAlbzbOnBtEkIV1V66mfyNayFMlCAGwNwjQ6OcjU=; h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=EjkanyEygvSp54lXCuoFwNNeGpSyeXr30UUlsagOcKVeeezu18uqRhkshPJCyr1ER JxOY0yw/Zj4K+UFx+sUQxq1Px+8MNJb94UQ9h+kS/mZPTwG/uYkTRvpRPscGpRBZYs u0xbXFWVhCKNSy0PJZEb0CTPJRAd0/5FQoj2/8fM= X-Original-To: cygwin AT cygwin DOT com Delivered-To: cygwin AT cygwin DOT com DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D4B2C3839C55 Date: Thu, 10 Apr 2025 11:04:40 +0200 To: cygwin AT cygwin DOT com Subject: Re: pthread_atfork vs dlopen/dlclose Message-ID: Mail-Followup-To: cygwin AT cygwin DOT com References: <07665688-8199-2e80-cdfe-abeaa6f56ba7 AT jdrake DOT com> <2021152719 DOT 99592 DOT 1744265074916 AT mail DOT yahoo DOT com> <94af5480-167a-fcc6-5f4c-89afa5ce8637 AT jdrake DOT com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <94af5480-167a-fcc6-5f4c-89afa5ce8637@jdrake.com> X-BeenThere: cygwin AT cygwin DOT com X-Mailman-Version: 2.1.30 Precedence: list List-Id: General Cygwin discussions and problem reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Corinna Vinschen via Cygwin Reply-To: cygwin AT cygwin DOT com Cc: Corinna Vinschen Content-Type: text/plain; charset="utf-8" Errors-To: cygwin-bounces~archive-cygwin=delorie DOT com AT cygwin DOT com Sender: "Cygwin" Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from base64 to 8bit by delorie.com id 53A96JVu3180803 On Apr 9 23:32, Jeremy Drake via Cygwin wrote: > On Wed, 9 Apr 2025, Jeremy Drake via Cygwin wrote: > > > On Thu, 10 Apr 2025, Kevin Schnitzius via Cygwin wrote: > > > > > On Wednesday, April 9, 2025 at 06:54:34 PM EDT, Jeremy Drake via Cygwin wrote: > > > > > > > The recent issue with pthread_atfork handlers reminded me of a scenario > > > > that I know glibc handles, but it seems that Cygwin does not.  Test case: > > > > > > <... code that loads a shared lib, registers some functions in shared lib with pthread_atfork(), unloads the shared lib, and crashes on fork...> > > > > > > Calling functions in an unloaded library should result in undefined behavior. > > > > > > However, further investigation reveals that the Linux pthread_atfork() registered functions are not being called and POSIX does not proved a mechanism for un-registering these functions.   Note: pthread_atfork() is not bumping the ref count on the shared lib--those functions are definitely unavailable after the dlclose() > > > > > > In the Cygwin version, calling the functions in the unloaded library when the fork happens causes the crash. > > > > > > This seems to be a bug with fork(), if it is a bug at all. > > > > I did a quick search, and found a write-up of *my* bug report :D > > > > https://developers.redhat.com/articles/2022/12/14/how-we-addressed-unforeseen-use-case-pthreadatfork > > > > "Now, dlclose()'ing a module means that any fork handlers registered by it > > should not be executed after the dlclose and should therefore implicitly > > be deregistered." > > It seems glibc takes care of this implicit deregistration in > __cxa_finalize, after calling __cxa_atexit functions, it unregisters any > at_quick_exit or pthread_atfork callbacks from the DSO being unloaded. > > https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/cxa_finalize.c;h=2bb35602edc6bf842e5d2c93ad03454d7b57ee65;hb=HEAD > > It doesn't look like newlib deals with either at_quick_exit or > pthread_atfork handlers in its __cxa_finalize implementation. Cygwin is doing this stuff mostly in its own code, see thread.cc. It keeps lists of the callbacks in a global structure which is called MT_INTERFACE throughout thread.cc. The functions pthread::atforkprepare(), pthread::atforkparent() and pthread::atforkchild () are called from different spots during fork(). Here's what we're missing: - Either keep track of the DLL a callback function is coming from by calling dlls.find (handle, true) and store the struct dll pointer. In dlclose(), if the DLL is of type DLL_LOAD or DLL_NATIVE, and the refcounter indicates that this is the last FreeLibrary, check the three callback lists in MT_INTERFACE and remove all functions with the same struct dll pointer. - Or, instead of keeping track, tweak the aformentioned three functions to call GetModuleHandleEx() just as dladdr() does, and if it returns NULL, remove the callback from the list on the fly. Corinna -- Problem reports: https://cygwin.com/problems.html FAQ: https://cygwin.com/faq/ Documentation: https://cygwin.com/docs.html Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple