Windows crash: [mutex.cc : 2600] RAW: Check waitp->thread->waitp == nullptr failed: waiting when shouldn't be

39 views
Skip to first unread message

Jeroen Ooms

unread,
Sep 27, 2025, 5:55:38 AM9/27/25
to v8-...@googlegroups.com
I maintain bindings for V8 for the R programming language. We run into a difficult problem: applications that run WASM seem to be random crashing on Windows 2025 with the following error:

   [mutex.cc : 2600] RAW: Check waitp->thread->waitp == nullptr failed: waiting when shouldn't be

This error originates in abseil. I tested this both with V8 14.0.365.4 and 14.1.146.11. Strangely it never happens on Windows 2022; but we found in other instances as well that Windows 2025 has become more strict/sensitive about memory and threading bugs.

Besides being non deterministic, what makes this difficult to reproduce is that we have to compile with gcc from mingw-w64 (we use mingw-w64-v8 on msys2).

Any hint to which component of v8 could be related to this?

Jeroen Ooms

unread,
Apr 14, 2026, 5:52:32 AM (5 days ago) Apr 14
to v8-dev
Claude found the problem. Attached the patch that fixed the occasional crash.

Two related fixes for abseil-cpp when built with MinGW-w64: 1. Force ABSL_THREAD_IDENTITY_MODE_USE_CPP11 on MinGW. On MinGW, abseil selects ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC because it is excluded from the _WIN32 && !__MINGW32__ CPP11 branch. In POSIX_SETSPECIFIC mode ClearCurrentThreadIdentity() is a no-op (only an assert in Release builds). It relies entirely on the pthread runtime clearing the key value before invoking the destructor. With MinGW's winpthreads and threads created via _beginthreadex (as V8 does), that guarantee can fail: the dying thread's TLS slot is not always cleared before ReclaimThreadIdentity() returns the identity to the free list. A new thread then allocates that same identity, but the old thread still has a live TLS reference to it. When V8's WASM engine creates many worker threads (14.x regression vs 11.x) the race becomes frequent enough to trigger the abseil Mutex assertion: Check waitp->thread->waitp == nullptr failed: waiting when shouldn't be In CPP11 mode ClearCurrentThreadIdentity() sets thread_identity_ptr=nullptr before the identity is recycled, closing the aliasing window. This is already the mode used by MSVC (_WIN32 && !__MINGW32__); we extend it to cover MinGW as well. 2. Enable Win32Waiter for MinGW. abseil explicitly excludes MinGW from Win32Waiter (which uses the native SRWLOCK / CONDITION_VARIABLE APIs), falling back to StdcppWaiter. Modern MinGW-w64 as shipped by MSYS2 fully supports these Vista+ APIs. Using Win32Waiter avoids the StdcppWaiter's stale waiter_count_/wakeup_count_ fields on identity reuse (because those fields can be non-zero when an identity is recycled), and also gives better performance. diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h --- a/absl/base/internal/thread_identity.h +++ b/absl/base/internal/thread_identity.h @@ -268,6 +268,14 @@ ABSL_NAMESPACE_END #ifdef ABSL_THREAD_IDENTITY_MODE #error ABSL_THREAD_IDENTITY_MODE cannot be directly set #elif defined(ABSL_FORCE_THREAD_IDENTITY_MODE) #define ABSL_THREAD_IDENTITY_MODE ABSL_FORCE_THREAD_IDENTITY_MODE +#elif defined(__MINGW32__) && defined(ABSL_HAVE_THREAD_LOCAL) +// MinGW's winpthreads does not reliably clear pthread TLS before calling key +// destructors for _beginthreadex-created threads (as used by V8). Use C++11 +// thread_local so that ClearCurrentThreadIdentity() sets thread_identity_ptr +// to nullptr before the identity is placed on the free list, preventing a +// second thread from aliasing the same ThreadIdentity object. +#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11 #elif defined(_WIN32) && !defined(__MINGW32__) #define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11 #elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL) diff --git a/absl/synchronization/internal/win32_waiter.h b/absl/synchronization/internal/win32_waiter.h --- a/absl/synchronization/internal/win32_waiter.h +++ b/absl/synchronization/internal/win32_waiter.h @@ -21,8 +21,8 @@ #endif -#if defined(_WIN32) && !defined(__MINGW32__) && \ - _WIN32_WINNT >= _WIN32_WINNT_VISTA +// MinGW-w64 ships SRWLOCK/CONDITION_VARIABLE support; enable Win32Waiter. +#if defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA #include "absl/base/config.h" #include "absl/synchronization/internal/kernel_timeout.h" @@ -67,7 +67,6 @@ ABSL_NAMESPACE_END } // namespace absl -#endif // defined(_WIN32) && !defined(__MINGW32__) && - // _WIN32_WINNT >= _WIN32_WINNT_VISTA +#endif // defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA #endif // ABSL_SYNCHRONIZATION_INTERNAL_WIN32_WAITER_H_
017-abseil-mingw-thread-fixes.patch
Reply all
Reply to author
Forward
0 new messages