diff options
author | Ry Dahl <ry@tinyclouds.org> | 2019-10-19 17:09:24 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-19 17:09:24 -0400 |
commit | 4ae1838a6ebadbe156af101e298ffb8b198cc238 (patch) | |
tree | bca213099edf0fade296e446cea444f0488bd171 /cli/js | |
parent | c876d1adb40a79e7a052ae0ae1b1956a4a0866ea (diff) |
Fix clearTimer bug (#3143)
Diffstat (limited to 'cli/js')
-rw-r--r-- | cli/js/timers.ts | 7 | ||||
-rw-r--r-- | cli/js/timers_test.ts | 12 |
2 files changed, 17 insertions, 2 deletions
diff --git a/cli/js/timers.ts b/cli/js/timers.ts index 5bc4922e3..9ebe4f6cb 100644 --- a/cli/js/timers.ts +++ b/cli/js/timers.ts @@ -44,16 +44,19 @@ function clearGlobalTimeout(): void { sendSync(dispatch.OP_GLOBAL_TIMER_STOP); } +let pendingEvents = 0; + async function setGlobalTimeout(due: number, now: number): Promise<void> { // Since JS and Rust don't use the same clock, pass the time to rust as a // relative time value. On the Rust side we'll turn that into an absolute // value again. const timeout = due - now; assert(timeout >= 0); - // Send message to the backend. globalTimeoutDue = due; + pendingEvents++; await sendAsync(dispatch.OP_GLOBAL_TIMER, { timeout }); + pendingEvents--; // eslint-disable-next-line @typescript-eslint/no-use-before-define fireTimers(); } @@ -139,7 +142,7 @@ function fire(timer: Timer): void { function fireTimers(): void { const now = getTime(); // Bail out if we're not expecting the global timer to fire. - if (globalTimeoutDue === null) { + if (globalTimeoutDue === null || pendingEvents > 0) { return; } // After firing the timers that are due now, this will hold the due time of diff --git a/cli/js/timers_test.ts b/cli/js/timers_test.ts index bc4fcffcf..b5e3574cf 100644 --- a/cli/js/timers_test.ts +++ b/cli/js/timers_test.ts @@ -289,3 +289,15 @@ test(function testFunctionParamsLength(): void { test(function clearTimeoutAndClearIntervalNotBeEquals(): void { assertNotEquals(clearTimeout, clearInterval); }); + +test(async function timerMaxCpuBug(): Promise<void> { + // There was a bug where clearing a timeout would cause Deno to use 100% CPU. + clearTimeout(setTimeout(() => {}, 1000)); + // We can check this by counting how many ops have triggered in the interim. + // Certainly less than 10 ops should have been dispatched in next 100 ms. + const { opsDispatched } = Deno.metrics(); + await waitForMs(100); + const opsDispatched_ = Deno.metrics().opsDispatched; + console.log("opsDispatched", opsDispatched, "opsDispatched_", opsDispatched_); + assert(opsDispatched_ - opsDispatched < 10); +}); |