That seems to fix some (difficult to reproduce) crashes in EA Desktop / CEF, usually on shutdown but sometimes during starting up.
Currently TpSetWait can set (or clear) the event, while waitqueue_thread_proc() gets woken from NtWaitForMultipleObjects by previously set wait object and call the callback as if new set (or cleared) wait object is signaled. The crashes I was reproducing were always happening when RtlDeregisterWaitEx call is racing with waking the wait and calling the callback.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/threadpool.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c index 4f22114a55e..9a8f380bf72 100644 --- a/dlls/ntdll/threadpool.c +++ b/dlls/ntdll/threadpool.c @@ -1265,6 +1265,7 @@ static void CALLBACK waitqueue_thread_proc( void *param ) u.wait.wait_entry ) { assert( wait->type == TP_OBJECT_TYPE_WAIT ); + assert( wait->u.wait.wait_pending ); if (wait->u.wait.timeout <= now.QuadPart) { /* Wait object timed out. */ @@ -1272,6 +1273,7 @@ static void CALLBACK waitqueue_thread_proc( void *param ) { list_remove( &wait->u.wait.wait_entry ); list_add_tail( &bucket->reserved, &wait->u.wait.wait_entry ); + wait->u.wait.wait_pending = FALSE; } if ((wait->u.wait.flags & (WT_EXECUTEINWAITTHREAD | WT_EXECUTEINIOTHREAD))) { @@ -1329,6 +1331,7 @@ static void CALLBACK waitqueue_thread_proc( void *param ) { list_remove( &wait->u.wait.wait_entry ); list_add_tail( &bucket->reserved, &wait->u.wait.wait_entry ); + wait->u.wait.wait_pending = FALSE; } if ((wait->u.wait.flags & (WT_EXECUTEINWAITTHREAD | WT_EXECUTEINIOTHREAD))) {
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/threadpool.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c index 9a8f380bf72..d0671490083 100644 --- a/dlls/ntdll/threadpool.c +++ b/dlls/ntdll/threadpool.c @@ -160,6 +160,7 @@ struct threadpool_object LONG num_pending_callbacks; LONG num_running_callbacks; LONG num_associated_callbacks; + LONG update_serial; /* arguments for callback */ union { @@ -1243,6 +1244,7 @@ static void tp_timerqueue_unlock( struct threadpool_object *timer ) static void CALLBACK waitqueue_thread_proc( void *param ) { struct threadpool_object *objects[MAXIMUM_WAITQUEUE_OBJECTS]; + LONG update_serials[MAXIMUM_WAITQUEUE_OBJECTS]; HANDLE handles[MAXIMUM_WAITQUEUE_OBJECTS + 1]; struct waitqueue_bucket *bucket = param; struct threadpool_object *wait, *next; @@ -1295,6 +1297,7 @@ static void CALLBACK waitqueue_thread_proc( void *param ) InterlockedIncrement( &wait->refcount ); objects[num_handles] = wait; handles[num_handles] = wait->u.wait.handle; + update_serials[num_handles] = wait->update_serial; num_handles++; } } @@ -1323,7 +1326,7 @@ static void CALLBACK waitqueue_thread_proc( void *param ) { wait = objects[status - STATUS_WAIT_0]; assert( wait->type == TP_OBJECT_TYPE_WAIT ); - if (wait->u.wait.bucket) + if (wait->u.wait.bucket && wait->update_serial == update_serials[status - STATUS_WAIT_0]) { /* Wait object signaled. */ assert( wait->u.wait.bucket == bucket ); @@ -1344,7 +1347,10 @@ static void CALLBACK waitqueue_thread_proc( void *param ) else tp_object_submit( wait, TRUE ); } else - WARN("wait object %p triggered while object was destroyed\n", wait); + { + WARN("wait object %p triggered while object was %s.\n", + wait, wait->u.wait.bucket ? "updated" : "destroyed"); + } }
/* Release temporary references to wait objects. */ @@ -1917,6 +1923,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa object->num_pending_callbacks = 0; object->num_running_callbacks = 0; object->num_associated_callbacks = 0; + object->update_serial = 0;
if (environment) { @@ -3057,6 +3064,9 @@ VOID WINAPI TpSetWait( TP_WAIT *wait, HANDLE handle, LARGE_INTEGER *timeout ) RtlEnterCriticalSection( &waitqueue.cs );
assert( this->u.wait.bucket ); + if (this->u.wait.handle == handle) + goto done; + this->u.wait.handle = handle;
if (handle || this->u.wait.wait_pending) @@ -3090,9 +3100,11 @@ VOID WINAPI TpSetWait( TP_WAIT *wait, HANDLE handle, LARGE_INTEGER *timeout ) }
/* Wake up the wait queue thread. */ + ++this->update_serial; NtSetEvent( bucket->update_event, NULL ); }
+done: RtlLeaveCriticalSection( &waitqueue.cs ); }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=142865
Your paranoid android.
=== debian11 (32 bit report) ===
ntdll: threadpool.c:1700: Test failed: expected info.userdata = 0x10000, got 0 threadpool.c:1771: Test failed: expected info.userdata = 0x10000, got 0 threadpool.c:1796: Test failed: expected info.userdata = 0x10000, got 0 threadpool.c:1867: Test failed: expected info.userdata = 2, got 1 threadpool.c:1965: Test failed: expected result 511, got 0 threadpool.c:1965: Test failed: expected result 510, got 0 threadpool.c:1965: Test failed: expected result 509, got 0 threadpool.c:1965: Test failed: expected result 508, got 0 threadpool.c:1965: Test failed: expected result 507, got 0 threadpool.c:1965: Test failed: expected result 506, got 0 threadpool.c:1965: Test failed: expected result 505, got 0 threadpool.c:1965: Test failed: expected result 504, got 0 threadpool.c:1965: Test failed: expected result 503, got 0 threadpool.c:1965: Test failed: expected result 502, got 0 threadpool.c:1965: Test failed: expected result 501, got 0 threadpool.c:1965: Test failed: expected result 500, got 0 threadpool.c:1965: Test failed: expected result 499, got 0 threadpool.c:1965: Test failed: expected result 498, got 0 threadpool.c:1965: Test failed: expected result 497, got 0 threadpool.c:1965: Test failed: expected result 496, got 0 threadpool.c:1965: Test failed: expected result 495, got 0 threadpool.c:1965: Test failed: expected result 494, got 0 threadpool.c:1965: Test failed: expected result 493, got 0 threadpool.c:1965: Test failed: expected result 492, got 0 threadpool.c:1965: Test failed: expected result 491, got 0 threadpool.c:1965: Test failed: expected result 490, got 0 threadpool.c:1965: Test failed: expected result 489, got 0 threadpool.c:1965: Test failed: expected result 488, got 0 threadpool.c:1965: Test failed: expected result 487, got 0 threadpool.c:1965: Test failed: expected result 486, got 0 threadpool.c:1965: Test failed: expected result 485, got 0 threadpool.c:1965: Test failed: expected result 484, got 0 threadpool.c:1965: Test failed: expected result 483, got 0 threadpool.c:1965: Test failed: expected result 482, got 0 threadpool.c:1965: Test failed: expected result 481, got 0 threadpool.c:1965: Test failed: expected result 480, got 0 threadpool.c:1965: Test failed: expected result 479, got 0 threadpool.c:1965: Test failed: expected result 478, got 0 threadpool.c:1965: Test failed: expected result 477, got 0 threadpool.c:1965: Test failed: expected result 476, got 0 threadpool.c:1965: Test failed: expected result 475, got 0 threadpool.c:1965: Test failed: expected result 474, got 0 threadpool.c:1965: Test failed: expected result 473, got 0 threadpool.c:1965: Test failed: expected result 472, got 0 threadpool.c:1965: Test failed: expected result 471, got 0 threadpool.c:1965: Test failed: expected result 470, got 0 threadpool.c:1965: Test failed: expected result 469, got 0 threadpool.c:1965: Test failed: expected result 468, got 0 threadpool.c:1965: Test failed: expected result 467, got 0 threadpool.c:1965: Test failed: expected result 466, got 0 threadpool.c:1965: Test failed: expected result 465, got 0 threadpool.c:1965: Test failed: expected result 464, got 0 threadpool.c:1965: Test failed: expected result 463, got 0 threadpool.c:1965: Test failed: expected result 462, got 0 threadpool.c:1965: Test failed: expected result 461, got 0 threadpool.c:1965: Test failed: expected result 460, got 0 threadpool.c:1965: Test failed: expected result 459, got 0 threadpool.c:1965: Test failed: expected result 458, got 0 threadpool: Timeout
=== debian11b (64 bit WoW report) ===
ntdll: threadpool.c:935: Test failed: WaitForSingleObject returned 258 threadpool.c:1699: Test failed: WaitForSingleObject returned 258 threadpool.c:1700: Test failed: expected info.userdata = 0x10000, got 0 threadpool.c:1713: Test failed: WaitForSingleObject returned 258 threadpool.c:1731: Test failed: WaitForSingleObject returned 258 threadpool.c:1734: Test failed: WaitForSingleObject returned 0 threadpool.c:1746: Test failed: WaitForSingleObject returned 258 threadpool.c:1770: Test failed: WaitForSingleObject returned 258 threadpool.c:1771: Test failed: expected info.userdata = 0x10000, got 0 threadpool.c:1785: Test failed: WaitForSingleObject returned 258 threadpool.c:1788: Test failed: WaitForSingleObject returned 0 threadpool.c:1795: Test failed: WaitForSingleObject returned 258 threadpool.c:1796: Test failed: expected info.userdata = 0x10000, got 0 threadpool.c:1866: Test failed: WaitForSingleObject returned 258 threadpool.c:1867: Test failed: expected info.userdata = 2, got 1 threadpool.c:1869: Test failed: WaitForSingleObject returned 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 511, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 510, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 509, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 508, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 507, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 506, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 505, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 504, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 503, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 502, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 501, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 500, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 499, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 498, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 497, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 496, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 495, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 494, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 493, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 492, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 491, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 490, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 489, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 488, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 487, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 486, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 485, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 484, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 483, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 482, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 481, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 480, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 479, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 478, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 477, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 476, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 475, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 474, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 473, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 472, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 471, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 470, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 469, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 468, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 467, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 466, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 465, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 464, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 463, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 462, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 461, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 460, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 459, got 0 threadpool.c:1964: Test failed: WaitForSingleObject returned 258 threadpool.c:1965: Test failed: expected result 458, got 0 threadpool: Timeout