Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the behaviour of setTimeout across an OS sleep/suspend defined?

I set a setTimeout for example 10s, and during that 10s, I suspend/sleep the PC. On awaken, which of the following is true:-

  1. The timeout is guaranteed to fire
  2. The timeout is guaranteed to not fire
  3. The timeout may or may not fire. It's browser-specific

Same question for a recurring setInterval. Is it guaranteed to (not) continue.

like image 753
pinoyyid Avatar asked Apr 05 '15 13:04

pinoyyid


2 Answers

Short Answer

It is defined to execute in the spec. The timeout request will go into a queue of sorts and poll until it can get fired. If the system sleeps upon resume it will pick up where it left off and resuming polling.

Long Answer probably more than anyone cares to know

The most recent (Oct 28th, 2014) working-draft of the Timer's Spec at the time of answer as written by the w3, it will fire... so long as the OS doesn't mess-up in the process of going to sleep/suspending and waking/resuming (external to the scope). It's more of an OS level question, but as far as the w3 spec goes, it will eventually fire.

Both the setInterval(...) and setTimeout(...) go off of the same windowTimer interface which the window object for the browser implements.

In both cases, The client defines either an interval or a timeout request to which the method context undergoes an timer initialization steps where it is added to a list of active timers and a handle is returned for a scheduled task.

Once in the list of active timers, the system will queue the task to execute at or after the requested duration of time (pending other tasks with higher priority as well as CPU load). If a task cannot reserve CPU time, it will poll/wait until it can. So if the system sleeps upon resume it will pick up where it left off.

In order for a task to execute, it's handle must exist in list of active timers. After task has run, if the repeat flag is set to true (if it was created with setInterval(...)) the task will be recreated with the same parameters and assigned the same exact same handle. In other words it gets added back into the queue/list to be executed at or after the next interval.

The following is the only note or remark in the Timer spec about the system removing items from the list of active timers:

Once the task has been processed, if the repeat flag is false, it is safe to remove the entry for handle from the list of active timers (there is no way for the entry's existence to be detected past this point, so it does not technically matter one way or the other)

According to the spec if it is in the list of active timers when the task is ran, it will fire as expected. Otherwise it is aborted. So back to my first point, if the OS doesn't mess things up during the sleep/suspend process upon resuming the task continue to poll. Once it gets CPU time it's handle should still exist in the list of active timers and thus upon being processed will execute.

like image 181
Arthur Weborg Avatar answered Sep 21 '22 14:09

Arthur Weborg


I just tested it with this script:

<html>
<body>
<script>
var d = 120;
var start = new Date ();
document.write(start + " : sleeping for " + d + " seconds");
</script>
<div id='result'><div>
<script>
function cb() {
  var now = new Date ();
  document.getElementById("result").innerHTML = "" + Date () + " : callback fired after " + (now.getTime() - start.getTime()) / 1000 + " seconds";
};
window.setTimeout(cb, d * 1000);
</script>
</body>
</html>

I opened the page in Firefox 37.0.1 and Chromium 41.0.2272.118 (64-bit), then suspended my machine for a couple of minutes. When I resumed, both browsers waited a couple more minutes even though the timer was due. Example output (machine was resumed at Wed 15 Apr 17:52:11 BST 2015):

Wed Apr 15 2015 17:49:13 GMT+0100 (BST) : sleeping for 120 seconds
Wed Apr 15 2015 17:53:47 GMT+0100 (BST) : callback fired after 273.705 seconds
like image 32
Thomas Leonard Avatar answered Sep 17 '22 14:09

Thomas Leonard