Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
2b287a44
Commit
2b287a44
authored
Jul 25, 2008
by
Dan Hipschman
Committed by
Alexandre Julliard
Jul 28, 2008
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Fix a small timer-queue bug whereby a deleted timer may still expire.
parent
a0abf988
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
60 additions
and
4 deletions
+60
-4
sync.c
dlls/kernel32/tests/sync.c
+57
-1
threadpool.c
dlls/ntdll/threadpool.c
+3
-3
No files found.
dlls/kernel32/tests/sync.c
View file @
2b287a44
...
...
@@ -609,11 +609,45 @@ static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
Sleep
(
delay
);
}
static
void
CALLBACK
timer_queue_cb6
(
PVOID
p
,
BOOLEAN
timedOut
)
{
struct
timer_queue_data1
*
d
=
p
;
ok
(
timedOut
,
"Timer callbacks should always time out
\n
"
);
/* This tests an original implementation bug where a deleted timer may get
to run, but it is tricky to set up. */
if
(
d
->
q
&&
d
->
num_calls
++
==
0
)
{
/* First run: delete ourselves, then insert and remove a timer
that goes in front of us in the sorted timeout list. Once
removed, we will still timeout at the faster timer's due time,
but this should be a no-op if we are bug-free. There should
not be a second run. We can test the value of num_calls later. */
BOOL
ret
;
HANDLE
t
;
/* The delete will pend while we are in this callback. */
SetLastError
(
0xdeadbeef
);
ret
=
pDeleteTimerQueueTimer
(
d
->
q
,
d
->
t
,
NULL
);
ok
(
!
ret
,
"DeleteTimerQueueTimer
\n
"
);
ok
(
GetLastError
()
==
ERROR_IO_PENDING
,
"DeleteTimerQueueTimer
\n
"
);
ret
=
pCreateTimerQueueTimer
(
&
t
,
d
->
q
,
timer_queue_cb1
,
NULL
,
100
,
0
,
0
);
ok
(
ret
,
"CreateTimerQueueTimer
\n
"
);
ok
(
t
!=
NULL
,
"CreateTimerQueueTimer
\n
"
);
ret
=
pDeleteTimerQueueTimer
(
d
->
q
,
t
,
INVALID_HANDLE_VALUE
);
ok
(
ret
,
"DeleteTimerQueueTimer
\n
"
);
/* Now we stay alive by hanging around in the callback. */
Sleep
(
500
);
}
}
static
void
test_timer_queue
(
void
)
{
HANDLE
q
,
t1
,
t2
,
t3
,
t4
,
t5
;
int
n1
,
n2
,
n3
,
n4
,
n5
;
struct
timer_queue_data1
d2
,
d3
,
d4
;
struct
timer_queue_data1
d
1
,
d
2
,
d3
,
d4
;
HANDLE
e
,
et1
,
et2
;
BOOL
ret
;
...
...
@@ -824,6 +858,28 @@ static void test_timer_queue(void)
ok
(
d2
.
num_calls
==
d2
.
max_calls
,
"DeleteTimerQueueTimer
\n
"
);
ok
(
d3
.
num_calls
==
d3
.
max_calls
,
"ChangeTimerQueueTimer
\n
"
);
ok
(
d4
.
num_calls
==
1
,
"Timer flagged for deletion incorrectly
\n
"
);
/* Test an obscure bug that was in the original implementation. */
q
=
pCreateTimerQueue
();
ok
(
q
!=
NULL
,
"CreateTimerQueue
\n
"
);
/* All the work is done in the callback. */
d1
.
t
=
t1
=
NULL
;
d1
.
num_calls
=
0
;
d1
.
q
=
q
;
ret
=
pCreateTimerQueueTimer
(
&
t1
,
q
,
timer_queue_cb6
,
&
d1
,
100
,
100
,
WT_EXECUTELONGFUNCTION
);
d1
.
t
=
t1
;
ok
(
ret
,
"CreateTimerQueueTimer
\n
"
);
ok
(
t1
!=
NULL
,
"CreateTimerQueueTimer
\n
"
);
Sleep
(
750
);
SetLastError
(
0xdeadbeef
);
ret
=
pDeleteTimerQueueEx
(
q
,
NULL
);
ok
(
!
ret
,
"DeleteTimerQueueEx
\n
"
);
ok
(
GetLastError
()
==
ERROR_IO_PENDING
,
"DeleteTimerQueueEx
\n
"
);
ok
(
d1
.
num_calls
==
1
,
"DeleteTimerQueueTimer
\n
"
);
}
START_TEST
(
sync
)
...
...
dlls/ntdll/threadpool.c
View file @
2b287a44
...
...
@@ -643,7 +643,7 @@ static inline void queue_move_timer(struct queue_timer *t, ULONGLONG time,
static
void
queue_timer_expire
(
struct
timer_queue
*
q
)
{
struct
queue_timer
*
t
;
struct
queue_timer
*
t
=
NULL
;
RtlEnterCriticalSection
(
&
q
->
cs
);
if
(
list_head
(
&
q
->
timers
))
...
...
@@ -656,9 +656,9 @@ static void queue_timer_expire(struct timer_queue *q)
t
,
t
->
period
?
queue_current_time
()
+
t
->
period
:
EXPIRE_NEVER
,
FALSE
);
}
else
t
=
NULL
;
}
else
t
=
NULL
;
RtlLeaveCriticalSection
(
&
q
->
cs
);
if
(
t
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment