From 04cf2fe588987e58bb17e83b2a2c39f73a6bd23c Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sun, 9 Jun 2019 11:04:15 +0100 Subject: Window.bnd: Do not remove in-train callbacks Sometimes callbacks may be cancelled from within themselves. In that case we need to simply ensure that should the callback be wanted to repeat, we instead stop that so that once the callback is completed we do not attempt to reschedule something which had already been deleted. Signed-off-by: Daniel Silverstone --- content/handlers/javascript/duktape/Window.bnd | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/content/handlers/javascript/duktape/Window.bnd b/content/handlers/javascript/duktape/Window.bnd index 99615c207..731b2a335 100644 --- a/content/handlers/javascript/duktape/Window.bnd +++ b/content/handlers/javascript/duktape/Window.bnd @@ -36,6 +36,7 @@ typedef struct window_schedule_s { struct window_schedule_s *r_prev; size_t handle; int repeat_timeout; + bool running; } window_schedule_t; static void window_remove_callback_bits(duk_context *ctx, size_t handle) { @@ -100,7 +101,9 @@ static void window_schedule_callback(void *p) { NSLOG(dukky, DEEPDEBUG, "Entered window scheduler callback: %"PRIsizet, priv->handle); + priv->running = true; window_call_callback(priv->ctx, priv->handle, priv->repeat_timeout == 0); + priv->running = false; if (priv->repeat_timeout > 0) { /* Reschedule */ @@ -126,6 +129,7 @@ static size_t window_alloc_new_callback(duk_context *ctx, window_private_t *wind sched->ctx = ctx; sched->handle = new_handle; sched->repeat_timeout = repeating ? timeout : 0; + sched->running = false; RING_INSERT(window->schedule_ring, sched); @@ -171,14 +175,19 @@ static void window_remove_callback_by_handle(duk_context *ctx, RING_ITERATE_START(window_schedule_t, window->schedule_ring, sched) { if (sched->handle == handle) { - NSLOG(dukky, DEEPDEBUG, "Cancelled callback %"PRIsizet, sched->handle); - res = guit->misc->schedule(-1, - window_schedule_callback, - sched); - assert(res == NSERROR_OK); - RING_REMOVE(window->schedule_ring, sched); - window_remove_callback_bits(ctx, sched->handle); - free(sched); + if (sched->running) { + NSLOG(dukky, DEEPDEBUG, "Cancelling in-train callback %"PRIsizet, sched->handle); + sched->repeat_timeout = 0; + } else { + NSLOG(dukky, DEEPDEBUG, "Cancelled callback %"PRIsizet, sched->handle); + res = guit->misc->schedule(-1, + window_schedule_callback, + sched); + assert(res == NSERROR_OK); + RING_REMOVE(window->schedule_ring, sched); + window_remove_callback_bits(ctx, sched->handle); + free(sched); + } RING_ITERATE_STOP(window->schedule_ring, sched); } } RING_ITERATE_END(window->schedule_ring, sched); -- cgit v1.2.3