std::mutex bug: Windows handle growth

Frank Eskesen via Cygwin <[email protected]>
Newsgroups gmane.os.cygwin
Message-ID <[email protected]>
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.

When commenting out the lock_guard statement, there is no handle growth.

When changing the lock_guard to mutex.lock(), the handle growth increases
until an exception is thrown.

Surprisingly, when changing the lock_guard to mutex.unlock() handle growth
increases to about 16,880,000 and doesn't increase more. No exception 
occurs.
(mutex::unlock without mutex::lock is apparently allowed.)

The "Invalid argument" exception is presumably thrown somewhere in the mutex
locking code.

Console output:
/home/*******/obj/cpp/Test: Test_mutex
FAILED: Exception: exception(Invalid argument)

//----------------------------------------------------------------------------
//
// Title-
//       Test_mutex.cpp
//
// Purpose-
//       Mutex stress test.
//
// Last change date-
//       2026/03/16
//
//----------------------------------------------------------------------------
#include <exception>                // For std::exception
#include <mutex>                    // For std::mutex

#include <cstdio>                   // For printf
#include <ctime>                    // For timespec, clock_gettime

//----------------------------------------------------------------------------
// Constants for parameterization
//----------------------------------------------------------------------------
static double          opt_runtime= 60.0; // --runtime option

//----------------------------------------------------------------------------
//
// Subroutine-
//       now
//
// Purpose-
//       Return the number of seconds since the PC epoch.
//
//----------------------------------------------------------------------------
static double                       // Seconds since the PC epoch
    now( void )                      // Get the current time
{
    struct timespec     ticker;      // UTC time base

    clock_gettime(CLOCK_REALTIME, &ticker); //
    double seconds= (double)ticker.tv_sec;
    seconds += (double)ticker.tv_nsec / 1000000000.0;
    return seconds;
}

//----------------------------------------------------------------------------
//
// Subroutine-
//       do_something
//
// Purpose-
//       Do something that causes CYGWIN handle growth
//
//----------------------------------------------------------------------------
static void
    do_something(void)               // Try to cause CYGWIN handle growth
{
    std::mutex mutex;
    std::lock_guard<decltype(mutex)> lock(mutex);
}

//----------------------------------------------------------------------------
//
// Subroutine-
//       test_mutex
//
// Purpose-
//       std::mutex stress test.
//
//----------------------------------------------------------------------------
static inline void
    test_mutex( void )               // Timing test
{
    double then= now();              // Running timer
    while( (now() - then) < opt_runtime )
      do_something();
}

//----------------------------------------------------------------------------
//
// Subroutine-
//       main
//
// Purpose-
//       Mainline code.
//
//----------------------------------------------------------------------------
extern int
    main(int, char**)                // Mainline code
{
    try {
      test_mutex();
    } catch(std::exception& x) {
      printf("FAILED: Exception: exception(%s)\n", x.what());
    } catch(...) {
      printf("FAILED: Exception: ...\n");
    }

    return 0;
}


-- 
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.