[PATCH 4/7] ntoskrnl.exe: Avoid leaking events on multipe KeSetTimerEx() calls.
Paul Gofman
pgofman at codeweavers.com
Thu May 28 04:15:17 CDT 2020
As the consequent testing shows we can't just close the events on timer
reset. That would result in wrong wait results for current waiters.
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
dlls/ntoskrnl.exe/sync.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c
index 1954b8befb7..912dc046bac 100644
--- a/dlls/ntoskrnl.exe/sync.c
+++ b/dlls/ntoskrnl.exe/sync.c
@@ -83,9 +83,11 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
{
switch (objs[i]->Type)
{
+ case TYPE_MANUAL_TIMER:
case TYPE_MANUAL_EVENT:
objs[i]->WaitListHead.Blink = CreateEventW( NULL, TRUE, objs[i]->SignalState, NULL );
break;
+ case TYPE_AUTO_TIMER:
case TYPE_AUTO_EVENT:
objs[i]->WaitListHead.Blink = CreateEventW( NULL, FALSE, objs[i]->SignalState, NULL );
break;
@@ -99,9 +101,6 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
semaphore->Header.SignalState, semaphore->Limit, NULL );
break;
}
- case TYPE_MANUAL_TIMER:
- case TYPE_AUTO_TIMER:
- break;
}
}
@@ -137,6 +136,8 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
{
switch (objs[i]->Type)
{
+ case TYPE_AUTO_TIMER:
+ case TYPE_MANUAL_TIMER:
case TYPE_MANUAL_EVENT:
case TYPE_AUTO_EVENT:
case TYPE_SEMAPHORE:
@@ -394,7 +395,11 @@ static void CALLBACK ke_timer_complete_proc(PTP_CALLBACK_INSTANCE instance, void
TRACE("instance %p, timer %p, tp_timer %p.\n", instance, timer, tp_timer);
- SetEvent(timer->Header.WaitListHead.Blink);
+ EnterCriticalSection( &sync_cs );
+ timer->Header.SignalState = TRUE;
+ if (timer->Header.WaitListHead.Blink)
+ SetEvent(timer->Header.WaitListHead.Blink);
+ LeaveCriticalSection( &sync_cs );
}
/***********************************************************************
@@ -440,7 +445,6 @@ BOOLEAN WINAPI KeSetTimerEx( KTIMER *timer, LARGE_INTEGER duetime, LONG period,
ret = timer->Header.Inserted;
timer->Header.Inserted = TRUE;
- timer->Header.WaitListHead.Blink = CreateEventW( NULL, timer->Header.Type == TYPE_MANUAL_TIMER, FALSE, NULL );
if (!timer->TimerListEntry.Blink)
timer->TimerListEntry.Blink = (void *)CreateThreadpoolTimer(ke_timer_complete_proc, timer, NULL);
@@ -478,11 +482,15 @@ BOOLEAN WINAPI KeCancelTimer( KTIMER *timer )
timer->TimerListEntry.Blink = NULL;
}
}
+ timer->Header.SignalState = FALSE;
+ if (timer->Header.WaitListHead.Blink && !*((ULONG_PTR *)&timer->Header.WaitListHead.Flink))
+ {
+ CloseHandle(timer->Header.WaitListHead.Blink);
+ timer->Header.WaitListHead.Blink = NULL;
+ }
ret = timer->Header.Inserted;
timer->Header.Inserted = FALSE;
- CloseHandle(timer->Header.WaitListHead.Blink);
- timer->Header.WaitListHead.Blink = NULL;
LeaveCriticalSection( &sync_cs );
return ret;
--
2.26.2
More information about the wine-devel
mailing list