Closed Bug 831046 Opened 11 years ago Closed 5 months ago

Add a testing function for terminating execution as if the slow-script dialog intervened

Categories

(Core :: JavaScript Engine, enhancement)

enhancement

Tracking

()

RESOLVED FIXED

People

(Reporter: jruderman, Unassigned)

Details

(Keywords: sec-want)

I'd like a testing function or two (in the shell or in TestingFunctions) to help catch bugs involving "operation callbacks".

In particular, this should allow fuzzers to catch the kinds of bugs that bite the JS engine when the slow script dialog appears (see e.g. bug 806820 comment 31).


== Option 1 ==

terminateSoon(n, f)
  -> After |n| "operation callbacks", terminate execution, then call f().

Unlike terminate(), this would allow the fuzzer to keep going (even in the same context) after the execution stack is unwound.

Unlike timeout(), it would feel deterministic, or at least as deterministic as operation callbacks can be.


== Option 2 (scarier) ==

executeOnOperationCallback(n, f)
  -> After |n| "operation callbacks", call f().

terminateAndResume(f)
  -> Terminate execution of the current stack, then call f()
Option 2 won't work with the JITs.  Ion (and to a much lesser degree JM+TI) hoist property accesses and so forth out of loops, under the assumption that the operation callback does not have visible effects.  What are the cases when such effects are possible?  Is this only applicable to the debugger?
I'd thought the operation callback was supposed to be signal-handler-safe, as an API use requirement, but I could be wrong about that.  (Which would require what bhackett says in comment 1, to be clear.)
The decision we make in bug 831136 is likely to influence which API we want here.
After discussion on IRC, here's the API I think we should implement. It's more complicated, but it does ensure that all custom operation callbacks are temporary, which should make it more trustworthy to use in a browser context, as the normal "slow script" machinery will be restored once the test is done.

triggerOperationCallback([delay])
  Trigger an operation callback.

  If 'delay' is given, it must be a positive integer; wait that many operation
  callback opportunities to trigger the callback. (Note that delay counts only
  work when we are running a body function from 'withOperationCallback'.)

withOperationCallback(body, [callback])
  Call the function 'body', establishing the function 'callback' as the
  operation callback while 'body' runs. Once 'body' completes, restore the
  runtime's original operation callback. Return whatever value or throw whatever
  exception 'body' did.

  If 'callback' returns normally, resume execution in 'body'. If 'callback'
  returns a positive integer, trigger another operation callback after that many
  operation callback opportunities have passed. (Thus, if 'callback' returns
  zero, trigger another operation callback at the next opportunity.)

  If 'callback' throws or is terminated, then that is propagated to 'body'.

  While 'callback' runs, we temporarily restore the original operation callback.
  When we resume execution in 'body', 'callback' is reinstated.

  If 'callback' is omitted, then let triggering an operation callback simply
  terminate the execution of 'body' (as if by the 'terminate' function).
(In reply to Jeff Walden [:Waldo] (remove +bmo to email) from comment #2)
> I'd thought the operation callback was supposed to be signal-handler-safe,
> as an API use requirement, but I could be wrong about that.  (Which would
> require what bhackett says in comment 1, to be clear.)

*Triggering* the operation callback needs to be signal-safe, but the callback itself runs in a well-defined state. At present, in Firefox, we go and run arbitrary code from the operation callback handler: we pop up the slow script dialog, from which one can change focus to other windows, etc.
Assignee: general → nobody
Severity: normal → S3

I think this is fixed by the addition of interruptTest

Status: NEW → RESOLVED
Closed: 5 months ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.