util/timer: avoid deadlock when shutting down
When we shut down a guest we disable the timers. However this can cause deadlock if the guest has queued some async work that is trying to advance system time and spins forever trying to wind time forward. Pay attention to the return code and bail early if we can't wind time forward. Reported-by: Elisha Hollander <just4now666666@gmail.com> Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-Id: <20240916085400.1046925-15-alex.bennee@linaro.org>
This commit is contained in:
parent
ecbcc9ead2
commit
bc02be4508
@ -685,10 +685,17 @@ int64_t qemu_clock_advance_virtual_time(int64_t dest)
|
|||||||
{
|
{
|
||||||
int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
|
int64_t deadline;
|
||||||
|
|
||||||
aio_context = qemu_get_aio_context();
|
aio_context = qemu_get_aio_context();
|
||||||
while (clock < dest) {
|
|
||||||
int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
|
deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
|
||||||
QEMU_TIMER_ATTR_ALL);
|
QEMU_TIMER_ATTR_ALL);
|
||||||
|
/*
|
||||||
|
* A deadline of < 0 indicates this timer is not enabled, so we
|
||||||
|
* won't get far trying to run it forward.
|
||||||
|
*/
|
||||||
|
while (deadline >= 0 && clock < dest) {
|
||||||
int64_t warp = qemu_soonest_timeout(dest - clock, deadline);
|
int64_t warp = qemu_soonest_timeout(dest - clock, deadline);
|
||||||
|
|
||||||
qemu_virtual_clock_set_ns(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + warp);
|
qemu_virtual_clock_set_ns(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + warp);
|
||||||
@ -696,6 +703,9 @@ int64_t qemu_clock_advance_virtual_time(int64_t dest)
|
|||||||
qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
|
qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
|
||||||
timerlist_run_timers(aio_context->tlg.tl[QEMU_CLOCK_VIRTUAL]);
|
timerlist_run_timers(aio_context->tlg.tl[QEMU_CLOCK_VIRTUAL]);
|
||||||
clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||||
|
|
||||||
|
deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
|
||||||
|
QEMU_TIMER_ATTR_ALL);
|
||||||
}
|
}
|
||||||
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
|
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user