Commit 759e6f1d authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

ntdll: Avoid more race conditions in RtlDeregisterWaitEx.

af35aada left some issues unfixed. Instead of running the callback and returning a retval that indicates the callback is not running, we sometimes wait for it when we are not supposed to. Signed-off-by: 's avatarStefan Dösinger <stefan@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 3a2834b3
...@@ -81,7 +81,7 @@ struct wait_work_item ...@@ -81,7 +81,7 @@ struct wait_work_item
ULONG Flags; ULONG Flags;
HANDLE CompletionEvent; HANDLE CompletionEvent;
LONG DeleteCount; LONG DeleteCount;
BOOLEAN CallbackInProgress; int CallbackInProgress;
}; };
struct timer_queue; struct timer_queue;
...@@ -530,9 +530,14 @@ static DWORD CALLBACK wait_thread_proc(LPVOID Arg) ...@@ -530,9 +530,14 @@ static DWORD CALLBACK wait_thread_proc(LPVOID Arg)
wait_work_item->Context ); wait_work_item->Context );
TimerOrWaitFired = TRUE; TimerOrWaitFired = TRUE;
} }
wait_work_item->CallbackInProgress = TRUE; interlocked_xchg( &wait_work_item->CallbackInProgress, TRUE );
if (wait_work_item->CompletionEvent)
{
TRACE( "Work has been canceled.\n" );
break;
}
wait_work_item->Callback( wait_work_item->Context, TimerOrWaitFired ); wait_work_item->Callback( wait_work_item->Context, TimerOrWaitFired );
wait_work_item->CallbackInProgress = FALSE; interlocked_xchg( &wait_work_item->CallbackInProgress, FALSE );
if (wait_work_item->Flags & WT_EXECUTEONLYONCE) if (wait_work_item->Flags & WT_EXECUTEONLYONCE)
break; break;
...@@ -546,7 +551,8 @@ static DWORD CALLBACK wait_thread_proc(LPVOID Arg) ...@@ -546,7 +551,8 @@ static DWORD CALLBACK wait_thread_proc(LPVOID Arg)
{ {
completion_event = wait_work_item->CompletionEvent; completion_event = wait_work_item->CompletionEvent;
delete_wait_work_item( wait_work_item ); delete_wait_work_item( wait_work_item );
if (completion_event) NtSetEvent( completion_event, NULL ); if (completion_event && completion_event != INVALID_HANDLE_VALUE)
NtSetEvent( completion_event, NULL );
} }
return 0; return 0;
...@@ -637,14 +643,16 @@ NTSTATUS WINAPI RtlDeregisterWaitEx(HANDLE WaitHandle, HANDLE CompletionEvent) ...@@ -637,14 +643,16 @@ NTSTATUS WINAPI RtlDeregisterWaitEx(HANDLE WaitHandle, HANDLE CompletionEvent)
struct wait_work_item *wait_work_item = WaitHandle; struct wait_work_item *wait_work_item = WaitHandle;
NTSTATUS status; NTSTATUS status;
HANDLE LocalEvent = NULL; HANDLE LocalEvent = NULL;
BOOLEAN CallbackInProgress; int CallbackInProgress;
TRACE( "(%p %p)\n", WaitHandle, CompletionEvent ); TRACE( "(%p %p)\n", WaitHandle, CompletionEvent );
if (WaitHandle == NULL) if (WaitHandle == NULL)
return STATUS_INVALID_HANDLE; return STATUS_INVALID_HANDLE;
interlocked_xchg_ptr( &wait_work_item->CompletionEvent, INVALID_HANDLE_VALUE );
CallbackInProgress = wait_work_item->CallbackInProgress; CallbackInProgress = wait_work_item->CallbackInProgress;
TRACE( "callback in progress %u\n", CallbackInProgress );
if (CompletionEvent == INVALID_HANDLE_VALUE || !CallbackInProgress) if (CompletionEvent == INVALID_HANDLE_VALUE || !CallbackInProgress)
{ {
status = NtCreateEvent( &LocalEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE ); status = NtCreateEvent( &LocalEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE );
...@@ -666,6 +674,7 @@ NTSTATUS WINAPI RtlDeregisterWaitEx(HANDLE WaitHandle, HANDLE CompletionEvent) ...@@ -666,6 +674,7 @@ NTSTATUS WINAPI RtlDeregisterWaitEx(HANDLE WaitHandle, HANDLE CompletionEvent)
} }
else if (LocalEvent) else if (LocalEvent)
{ {
TRACE( "Waiting for completion event\n" );
NtWaitForSingleObject( LocalEvent, FALSE, NULL ); NtWaitForSingleObject( LocalEvent, FALSE, NULL );
status = STATUS_SUCCESS; status = STATUS_SUCCESS;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment