std::mutex bug: Windows handle growth

Corinna Vinschen corinna-cygwin@cygwin.com
Tue Mar 17 14:57:04 GMT 2026


On Mar 17 15:08, Corinna Vinschen via Cygwin wrote:
> On Mar 17 09:06, Noel Grandin via Cygwin wrote:
> > Hi
> > 
> > Hazarding a guess here:
> > 
> > On 3/16/2026 11:39 PM, Frank Eskesen via Cygwin wrote:
> > > 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
> > This code looks suspicious:
> > 
> >     pthread_mutex::destroy ()
> >     {
> >       if (condwaits || trylock ())
> >         // Do not destroy a condwaited or locked mutex
> >         return EBUSY;
> > 
> > I think it should be
> > 
> >       if (condwaits || !trylock ())
> 
> No, checking trylock() is correct.  pthread_mutex_destroy() must not
> destroy a busy mutex.  trylock() returns != 0 if the lock is busy.
> 
> Given the implementation of std::mutex is based on pthread_mutex,
> Frank's code is wrong, or at least somewhat borderline.  The mutex
> should first be unlocked before leaving do_something().
> 
> The reason this problem doesn't occur on Linux is the fact that mutexes
> are implemented without allocating a system object, so the
> pthread_mutex_destroy() function is basically a no-op, after checking if
> the lock is busy and returning 0 or EBUSY, whatever is right.

This looks like a bug in libstdc++ (trying with gcc 13.4.0).

I stepped through the do_something function, and what I can see is a
call to pthread_mutex_lock() from
std::lock_guard<std::mutex>::lock_guard() and a call to
pthread_mutex_unlock from std::lock_guard<std::mutex>::~lock_guard(),
but never a call to pthread_mutex_destroy().

I assume that the code in libstdc++ is using the underlying default
pthread code and simply assumes, that a destroy isn't required.


Corinna


More information about the Cygwin mailing list