diff options
author | wolfbeast <mcwerewolf@wolfbeast.com> | 2020-04-14 21:49:04 +0200 |
---|---|---|
committer | wolfbeast <mcwerewolf@wolfbeast.com> | 2020-04-14 21:49:04 +0200 |
commit | 39dac57259cff8b61db0b22cb2ad0a8adb02692e (patch) | |
tree | 52a026cc8c22793eb17fd0f5e22adce1ae08a1dd /toolkit/components/osfile/tests/xpcshell/test_osfile_kill.js | |
parent | a1cce3b2b00bbd9f4983013ddd8934a7bccb9e99 (diff) | |
parent | c2d9ab62f3d097c9e0e00184cab1f546554f5eaa (diff) | |
download | UXP-39dac57259cff8b61db0b22cb2ad0a8adb02692e.tar UXP-39dac57259cff8b61db0b22cb2ad0a8adb02692e.tar.gz UXP-39dac57259cff8b61db0b22cb2ad0a8adb02692e.tar.lz UXP-39dac57259cff8b61db0b22cb2ad0a8adb02692e.tar.xz UXP-39dac57259cff8b61db0b22cb2ad0a8adb02692e.zip |
Merge branch 'redwood' into 28.9-platform
Diffstat (limited to 'toolkit/components/osfile/tests/xpcshell/test_osfile_kill.js')
-rw-r--r-- | toolkit/components/osfile/tests/xpcshell/test_osfile_kill.js | 100 |
1 files changed, 0 insertions, 100 deletions
diff --git a/toolkit/components/osfile/tests/xpcshell/test_osfile_kill.js b/toolkit/components/osfile/tests/xpcshell/test_osfile_kill.js deleted file mode 100644 index e32c37224..000000000 --- a/toolkit/components/osfile/tests/xpcshell/test_osfile_kill.js +++ /dev/null @@ -1,100 +0,0 @@ -"use strict"; - -Components.utils.import("resource://gre/modules/osfile.jsm"); - -// We want the actual global to get at the internals since Scheduler is not -// exported. -var AsyncFrontGlobal = Components.utils.import( - "resource://gre/modules/osfile/osfile_async_front.jsm", - null); -var Scheduler = AsyncFrontGlobal.Scheduler; - -/** - * Verify that Scheduler.kill() interacts with other OS.File requests correctly, - * and that no requests are lost. This is relevant because on B2G we - * auto-kill the worker periodically, making it very possible for valid requests - * to be interleaved with the automatic kill(). - * - * This test is being created with the fix for Bug 1125989 where `kill` queue - * management was found to be buggy. It is a glass-box test that explicitly - * re-creates the observed failure situation; it is not guaranteed to prevent - * all future regressions. The following is a detailed explanation of the test - * for your benefit if this test ever breaks or you are wondering what was the - * point of all this. You might want to skim the code below first. - * - * OS.File maintains a `queue` of operations to be performed. This queue is - * nominally implemented as a chain of promises. Every time a new job is - * OS.File.push()ed, it effectively becomes the new `queue` promise. (An - * extra promise is interposed with a rejection handler to avoid the rejection - * cascading, but that does not matter for our purposes.) - * - * The flaw in `kill` was that it would wait for the `queue` to complete before - * replacing `queue`. As a result, another OS.File operation could use `push` - * (by way of OS.File.post()) to also use .then() on the same `queue` promise. - * Accordingly, assuming that promise was not yet resolved (due to a pending - * OS.File request), when it was resolved, both the task scheduled in `kill` - * and in `post` would be triggered. Both of those tasks would run until - * encountering a call to worker.post(). - * - * Re-creating this race is not entirely trivial because of the large number of - * promises used by the code causing control flow to repeatedly be deferred. In - * a slightly simpler world we could run the follwing in the same turn of the - * event loop and trigger the problem. - * - any OS.File request - * - Scheduler.kill() - * - any OS.File request - * - * However, we need the Scheduler.kill task to reach the point where it is - * waiting on the same `queue` that another task has been scheduled against. - * Since the `kill` task yields on the `killQueue` promise prior to yielding - * on `queue`, however, some turns of the event loop are required. Happily, - * for us, as discussed above, the problem triggers when we have two promises - * scheduled on the `queue`, so we can just wait to schedule the second OS.File - * request on the queue. (Note that because of the additional then() added to - * eat rejections, there is an important difference between the value of - * `queue` and the value returned by the first OS.File request.) - */ -add_task(function* test_kill_race() { - // Ensure the worker has been created and that SET_DEBUG has taken effect. - // We have chosen OS.File.exists for our tests because it does not trigger - // a rejection and we absolutely do not care what the operation is other - // than it does not invoke a native fast-path. - yield OS.File.exists('foo.foo'); - - do_print('issuing first request'); - let firstRequest = OS.File.exists('foo.bar'); - let secondRequest; - let secondResolved = false; - - // As noted in our big block comment, we want to wait to schedule the - // second request so that it races `kill`'s call to `worker.post`. Having - // ourselves wait on the same promise, `queue`, and registering ourselves - // before we issue the kill request means we will get run before the `kill` - // task resumes and allow us to precisely create the desired race. - Scheduler.queue.then(function() { - do_print('issuing second request'); - secondRequest = OS.File.exists('foo.baz'); - secondRequest.then(function() { - secondResolved = true; - }); - }); - - do_print('issuing kill request'); - let killRequest = Scheduler.kill({ reset: true, shutdown: false }); - - // Wait on the killRequest so that we can schedule a new OS.File request - // after it completes... - yield killRequest; - // ...because our ordering guarantee ensures that there is at most one - // worker (and this usage here should not be vulnerable even with the - // bug present), so when this completes the secondRequest has either been - // resolved or lost. - yield OS.File.exists('foo.goz'); - - ok(secondResolved, - 'The second request was resolved so we avoided the bug. Victory!'); -}); - -function run_test() { - run_next_test(); -} |