DMARC-Filter: OpenDMARC Filter v1.4.2 delorie.com 62HJAhFE1246576 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 62HJAhFE1246576 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=S8RrZuhZ X-Recipient: archive-cygwin AT delorie DOT com DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0DA2C4BBCDEE DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cygwin.com; s=default; t=1773774643; bh=tSLQ9hRE0jUUzBMPUlx1WDV7MATfL+QYwHCxoCIZl08=; 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=S8RrZuhZQS1gH36lcTwXY8MLqE+t71FosJKLEG+58t304uF6diGbyZ9xuFV0XSK0A SvAbrMwC2ebQ+qEZ+oQRHylZerSsgBOdKSxnYKh/8fMTpS6JKdlnK9kZuDe2AZI4xM 3nOhRUXGWy3v/n2/28g/kIR4kXfnhQk/ExGRh96A= X-Original-To: cygwin AT cygwin DOT com Delivered-To: cygwin AT cygwin DOT com DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7EF744BA23F1 Date: Tue, 17 Mar 2026 20:09:53 +0100 To: ASSI Subject: Re: std::mutex bug: Windows handle growth Message-ID: Mail-Followup-To: ASSI , cygwin AT cygwin DOT com References: <2d48a740-ce2b-4259-8947-f5c875dd1672 AT hvc DOT rr DOT com> <87tsue4ao5.fsf@> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <87tsue4ao5.fsf@> 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 , cygwin AT cygwin DOT com Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: cygwin-bounces~archive-cygwin=delorie DOT com AT cygwin DOT com Sender: "Cygwin" Note-from-DJ: This may be spam On Mar 17 18:40, ASSI via Cygwin wrote: > Frank Eskesen via Cygwin writes: > > I've run into a problem that occurs on Cygwin that doesn't occur on > > Linux systems: When a std::mutex is used, it doesn't clean up a > > Windows handle that it uses. This sample program demonstrates the > > problem, failing in under 60 seconds. Run this while using Window task > > manager to watch the handle count rise. On my machine, the count > > rapidly grows to about 16 million and then a std::exception is thrown. > > This is likely a bug in upstream libstadc++, more specifically by making > a wrong assumption about the behaviour of the pthread library. It looks > like Corinna has identified a potential workaround, but that is a bit > hack-ish and I'd rather not carry such a patch that will likely not get > accepted upstream. > > Can you please report this bug upstream and send the link to the > bugreport here? Meanwhile, I'd be interested to know if maybe that was > already fixed in a later version of gcc / libstdc++, so if you could try > one (or all) of the gcc test versions on your code that would be > helpful. My assumption is more or less correct, I was just looking cross-eyed into the class definition for a while. Here's the code in question from bits/std_mutex.h: --- SNIP --- class __mutex_base { protected: typedef __gthread_mutex_t __native_type; #ifdef __GTHREAD_MUTEX_INIT __native_type _M_mutex = __GTHREAD_MUTEX_INIT; constexpr __mutex_base() noexcept = default; #else __native_type _M_mutex; __mutex_base() noexcept { // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); } ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); } #endif __mutex_base(const __mutex_base&) = delete; __mutex_base& operator=(const __mutex_base&) = delete; }; --- SNAP --- The actual problem here is the `#ifdef __GTHREAD_MUTEX_INIT'. __GTHREAD_MUTEX_INIT translates into PTHREAD_MUTEX_INIT. If this is defined, you will notice the there's *no* destructor defined for class __mutex_base. Apparently the assumption is made that the underlying pthread_mutex_t type is a trivial type which doesn't need a destroy(), if PTHREAD_MUTEX_INIT exists. However, this is wrong for Cygwin. It defines PTHREAD_MUTEX_INIT, but it still needs a pthread_mutex_destroy() call, because the pthread_mutex_t type is not a trivial one. Thus, we need a destructor even if __GTHREAD_MUTEX_INIT is defined. A potential fix would be diff --git a/libstdc++-v3/include/bits/std_mutex.h b/libstdc++-v3/include/bits/std_mutex.h index 7ef33fe5d0d7..f060c75abf21 100644 --- a/libstdc++-v3/include/bits/std_mutex.h +++ b/libstdc++-v3/include/bits/std_mutex.h @@ -68,6 +68,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __native_type _M_mutex = __GTHREAD_MUTEX_INIT; constexpr __mutex_base() noexcept = default; +#ifdef __CYGWIN__ + ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); } +#endif #else __native_type _M_mutex; @Stromeko, can you please discuss this upstream? Thanks, 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