microtask timeouts (was Re: setImmediate)

# David Herman (12 years ago)

On Aug 12, 2013, at 5:43 PM, David Bruant <bruant.d at gmail.com> wrote:

  • I see no reasonable alternative to runaway microtask churn other than slow-script dialog.

So did Dominic [1]. I suggested something else [2] and he found the idea interesting. What do you think?

Quoting you from

[2] esdiscuss/2013-August/032630

you said:

Maybe implementations could decide to break a microtask chain, but instead of prompting a dialog, they just break it and call a callback (later, in a different task, not microtask) so that the script knows and can try to recover.

It is an interesting idea, I missed it the first time around; you might describe it as an asynchronous TimeoutException. I'm thinking about it, but I'm pretty skeptical. It's still effectively preemption semantics. At any nondeterministic (and not portably defined) point, your code can simply be stopped. It's not even clear what the atomicity guarantees would be around valid preemption points in the semantics. For example, can you preempt code halfway through the modification of a 64-bit word? Can you preempt code that hasn't spilled its registers back to memory? Am I scaring you yet? ;-)

Even if we could provide a fully well-specified definition for concurrent interruption, I really have no idea how code could ever realistically recover from such an event. The only thing the system tells you is "at some point in some turn we just stopped you from whatever you were doing," and now you're expected to reconstruct your state. This reminds me of exception safety in C++.

# Rafael Weinstein (12 years ago)

FWIW,

I very much agree with Dave on this point. My conceptual model for microtask work is just a re-ordering of work which otherwise would have run synchronously, but wanted to be run with a fresh stack.

Microtask non-termination should not be different from "regular" script non-termination.

# David Bruant (12 years ago)

Le 13/08/2013 03:09, David Herman a écrit :

It is an interesting idea, I missed it the first time around; you might describe it as an asynchronous TimeoutException. I'm thinking about it, but I'm pretty skeptical. It's still effectively preemption semantics. At any nondeterministic (and not portably defined) point, your code can simply be stopped. It's not even clear what the atomicity guarantees would be around valid preemption points in the semantics. For example, can you preempt code halfway through the modification of a 64-bit word? Can you preempt code that hasn't spilled its registers back to memory? Am I scaring you yet? ;-)

It could be decided that preemption can only happen between microtasks. That is still preemption, but less scary.

Even if we could provide a fully well-specified definition for concurrent interruption, I really have no idea how code could ever realistically recover from such an event. The only thing the system tells you is "at some point in some turn we just stopped you from whatever you were doing," and now you're expected to reconstruct your state. This reminds me of exception safety in C++.

I don't have more ideas than you, but the situation is not worse than the current slow-script dialog de facto standard. How do people recover today from when the user click "stop script"? With what I described, the programmer would have an equivalent experience, but this time, we don't bother the user with an annoying dialog which choice is almost impossible anyway (you really have to be JS-savvy and have deep understanding of the misbehaving webpage to decide to continue or end a script just based on file url and line number). And I drafted a mechanism that might help when trying to recover (but I'm really not an expert in these recovery scenarii, so more experts people can jump in.)

Note that this idea of a script-controlled timeout could be expanded in other places. For instance, DoS is a permanent and assumed threat from partially trusted code. With module loaders, the loader could decide that a given task/microtask from an untrusted function can never be longer than x milliseconds. This way, this threat can be under tight control. The module loader could be told anytime a module timed out and decide to just kill it if that happens too often, etc.

Also, maybe an equivalent feature could be added to function calls too. We could have Function.prototype.recoverableApply(this, args, onPreempted) (maybe recoverableBind too?) When the user clicks "kill script" during a "recoverable call" , the onPreempted function is schedule for a later turn and try to recover what it can (but we might have been preempted in one of the situation you described above, so... good luck, but that's not worse than today's situation)

# David Herman (12 years ago)

On Aug 12, 2013, at 6:32 PM, David Bruant <bruant.d at gmail.com> wrote:

How do people recover today from when the user click "stop script"?

They don't; it's a crash -- the web equivalent of "this application has stopped responding." You might as well ask for a solution to the halting problem! :)

# Brendan Eich (12 years ago)

David Herman wrote:

On Aug 12, 2013, at 6:32 PM, David Bruant<bruant.d at gmail.com> wrote:

How do people recover today from when the user click "stop script"?

They don't; it's a crash

(safe of course -- I'm a C hacker at heart :-P)

-- the web equivalent of "this application has stopped responding." You might as well ask for a solution to the halting problem!

Indeed the stop-script option (whatever its UX) is necessary to avoid denial of service, at the limit.

# David Bruant (12 years ago)

Le 13/08/2013 06:07, David Herman a écrit :

On Aug 12, 2013, at 6:32 PM, David Bruant <bruant.d at gmail.com> wrote:

How do people recover today from when the user click "stop script"?

They don't; it's a crash -- the web equivalent of "this application has stopped responding." You might as well ask for a solution to the halting problem! :)

Yes yes, my point exactly. So stopping a script between two microtasks can't be worse than what we have today. It's a rare event anyway.