New issue
Advanced search Search tips

Issue 828375 link

Starred by 3 users

Issue metadata

Status: Assigned
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 2
Type: Bug

Blocked on:
issue 402694



Sign in to add a comment

setInterval timing issue

Project Member Reported by jakearchibald@chromium.org, Apr 3 2018

Issue description

console.log('script start');

const interval = setInterval(() => {
  console.log('setInterval');
}, 0);

setTimeout(() => {
  console.log('setTimeout 1');
  Promise.resolve().then(() => {
    console.log('promise 3');
  }).then(() => {
    console.log('promise 4');
  }).then(() => {
    setTimeout(() => {
      console.log('setTimeout 2');
      Promise.resolve().then(() => {
        console.log('promise 5');
      }).then(() => {
        console.log('promise 6');
      }).then(() => {
        clearInterval(interval);
      });
    }, 0);
  });
}, 0);

Promise.resolve().then(() => {
  console.log('promise 1');
}).then(() => {
  console.log('promise 2');
});

-----

If I paste the above into the console, I get:

promise 1
promise 2
setInterval
setTimeout 1
promise 3
promise 4
setInterval
setInterval
setTimeout 2
promise 5
promise 6

Those two setIntervals in a row look like a spec violation. It may also be a race condition, but it shouldn't be.

Ignoring the microtasks (although they seem to be required to reproduce the issue), here's how things should happen:

Script executes, logs 'script start'. Task list:
* set interval task
* set timeout 1 task

Interval runs, logs 'setInterval', and requeues itself. Task list:
* set timeout 1 task
* set interval task

Timeout runs, logs 'setTimeout 1', and queues another timeout. Task list:
* set interval task
* set timeout 2 task

Interval runs, logs 'setInterval', and requeues itself. Task list:
* set timeout 2 task
* set interval task

^ This seems to be where things go wrong. The next interval task somehow happens before the next timeout task.

Timeout runs, logs 'setTimeout 2', and clears the interval. Task list:
* set interval task

Interval task runs, but exits before the callback because it's been cleared.

Although both setTimeout and setInterval may 'wait' a user-agent defined time before queueing a task, it mustn't result in callbacks happening in a different order from when they were scheduled (if the timeout is the same). From the spec: Wait until any invocations of this algorithm that had the same method context, that started before this one, and whose timeout is equal to or less than this one's, have completed. https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialisation-steps

 
Components: Blink>Scheduling
Status: Available (was: Untriaged)
I think the bug here might be that the setInterval delay is computed after clamping to 1ms/4ms [1], which means that setInterval can end up having a <1ms delay unlike setTimeout.

[1] https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/Timer.cpp?rcl=9a54951119a1f2493b994e24b0524512c97584e3&l=155
Components: Platform>Apps>DevTools
Looked into the issue: it seems that it repros when you are pasting the code into devtools console, but works normally when wrapped inside <script> tag and loaded as a page.

Adding Platform>Apps>DevTools for devtools folks to take a look.
Cc: l...@chromium.org
Any ideas luoe? Seems very strange.
Labels: -Pri-3 Pri-2
Cc: -l...@chromium.org
Components: -Platform>Apps>DevTools
Your assessment sounds reasonable to me, could someone on the timing/scheduling team please take a look?

I was able to reproduce the flaky single and double setInterval without using DevTools, but with a <script> in HTML, so removing DevTools label.  I tried on Linux 60.0.3112.0, 64.0.3282.0, and 70.0.3522.0.
intervalTiming.html
338 bytes View Download
Blockedon: 402694
Owner: altimin@chromium.org
Status: Assigned (was: Available)
Looks like there are two options here. Either we finally remove clamping of setTimeout(,0) or we add clamping to setInterval. IIRC altimin@ wanted to give the former another shot, so assigning this to him for now and blocking on 402694.

Sign in to add a comment