Bug 101268

Summary: Fixed flaky stack overflow test: fast/xmlhttprequest/xmlhttprequest-recursive-sync-event.html
Product: WebKit Reporter: Mark Lam <mark.lam>
Component: Tools / TestsAssignee: Mark Lam <mark.lam>
Status: RESOLVED FIXED    
Severity: Normal    
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
See Also: https://bugs.webkit.org/show_bug.cgi?id=139840
Attachments:
Description Flags
Fix. ggaren: review+

Mark Lam
Reported 2012-11-05 15:24:40 PST
Test fast/xmlhttprequest/xmlhttprequest-recursive-sync-event.html is flaky. Here's how we can make it not flaky: // This test is flaky because it depends on the size of the available native // stack, the size of native stack frames, and the layering of function calls // in the JavaScript VM code. Together, these variables determine when a // StackOverflowError will be thrown in the course of this test of unbounded // recursion. // // From experience with this test, StackOverflow error tends to be thrown in // 2 possible scenarios: // // Scenario 1: Overflowed while calling xhr.open() // =============================================== // In this scenario, the VM is executing xhr.open() and succeeds in setting // up the new request. In response to having opened the request, it tries to // dispatch an event with readyState 1 (OPENED). Unfortunately, there is not // enough stack and we get an overflow error and 1 console error message here. // // The error is thrown but is then eaten up by the EventDispatcher. Hence, // onreadystatechange() back in JS land does not even see this error. // // open() eventually returns to onreadystatechange(), and we call xhr.send() // next. xhr.send() overflows the stack again, and we get a 2nd error and // a 2nd console error message. // // Note: the lastReadyStateObserved in this case is 4 because the event // dispatch for OPENED failed to execute onreadystatechange(). // // The total number of error messages seen is 2. // // Scenario 2: Overflowed while calling xhr.send() // =============================================== // In this scenario, the VM is executing xhr.send() and a readyState change // to 4 (DONE) occurs. An event is dispatched and the VM tries to call // onreadystatechange() but overflows the stack. Here, we see 1 error and // 1 console error message. // // Since we never succeeded in reentering onreadystatechange(), we did not // not set up anymore requests, and will not attempt to re-enter // onreadystatechange() after this. Hence, we will not see anymore overflow // errors nor console error messages. // // In contrast with scenario 1, we did not see an overflow error for xhr.open() // before we saw the error for xhr.send(). // // Note: lastReadyStateObserved in this case is 1 because the event // dispatch for OPENED succeeded in executing onreadystatechange(), and // lastReadyStateObserved was set to 1. // // The total number of error messages seen is 1. // // Flakiness // ========= // Since we can end up with scenario 1 or 2 depending on variables outside the // control of this test, the result of the test would be inherently flaky i.e. // we can see 1 or 2 console error messages. // // That is unless we do some compensation. In the case of scenario 2, we can // check if the lastReadyStateObserved is 1 which means we would have only seen // one console error message. If so, we can call xhr.send() again just to // trigger another one so that we'll have a total of 2. // // Note that in the compensation case, we'll need to call xhr.open() again // before calling xhr.send(). This is because the previous xhr request has // already been closed. Here, xhr.open() should not trigger an overflow error // just like it didn't before the previous xhr.send() triggered the error (the // fact that it succeeded without an error before means it will succeed this // time too). And this leaves it up to our compensating call to xhr.send() // to generate the 2nd expected overflow error and console error message. // // Note also that we'll need to make sure that we do this compensation only // once, and not repeatedly do the compensating xhr.send() call on every // onreadystatechange() frame on the return path.
Attachments
Fix. (6.03 KB, patch)
2012-11-05 15:32 PST, Mark Lam
ggaren: review+
Mark Lam
Comment 1 2012-11-05 15:32:31 PST
Geoffrey Garen
Comment 2 2012-11-05 16:11:40 PST
Comment on attachment 172420 [details] Fix. Nice. I like this much better than just marking the test flaky in the testing harness.
Mark Lam
Comment 3 2012-11-05 16:25:41 PST
Note You need to log in before you can comment on or make changes to this bug.