Re: std::mutex bug: Windows handle growth
Corinna Vinschen via Cygwin <[email protected]>
| Newsgroups | gmane.os.cygwin |
|---|---|
| Message-ID | <[email protected]> |
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