fix: panic in worker when closing at top level (#8510)

Fixes panic occurring in worker when "self.close()" is called
at the top level, ie. worker shuts down while
module evaluation promise hasn't yet resolved.
This commit is contained in:
Bartek Iwańczuk 2020-11-27 14:19:24 +01:00 committed by GitHub
parent 28869a632d
commit 22f951aa67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 64 additions and 3 deletions

View file

@ -0,0 +1 @@
self.close();

View file

@ -3273,6 +3273,11 @@ itest!(ignore_require {
exit_code: 0,
});
itest!(local_sources_not_cached_in_memory {
args: "run --allow-read --allow-write no_mem_cache.js",
output: "no_mem_cache.js.out",
});
#[test]
fn cafile_env_fetch() {
use deno_core::url::Url;

33
cli/tests/no_mem_cache.js Normal file
View file

@ -0,0 +1,33 @@
const fixtureFile = await Deno.makeTempFile();
let prefix = "file://";
if (Deno.build.os == "windows") {
prefix += "/";
}
const fixtureUrl = new URL(`${prefix}${fixtureFile}`);
let resolve;
let p = new Promise((res) => resolve = res);
await Deno.writeTextFile(fixtureUrl, `self.postMessage("hello");\n`);
const workerA = new Worker(fixtureUrl.href, { type: "module" });
workerA.onmessage = (msg) => {
console.log(msg.data);
resolve();
};
await p;
workerA.terminate();
p = new Promise((res) => resolve = res);
await Deno.writeTextFile(fixtureUrl, `self.postMessage("goodbye");\n`);
const workerB = new Worker(fixtureUrl.href, { type: "module" });
workerB.onmessage = (msg) => {
console.log(msg.data);
resolve();
};
await p;
workerB.terminate();

View file

@ -0,0 +1,2 @@
hello
goodbye

View file

@ -341,3 +341,19 @@ Deno.test({
w.terminate();
},
});
Deno.test({
name: "Worker immediate close",
fn: async function (): Promise<void> {
const promise = deferred();
const w = new Worker(
new URL("./immediately_close_worker.js", import.meta.url).href,
{ type: "module" },
);
setTimeout(() => {
promise.resolve();
}, 1000);
await promise;
w.terminate();
},
});

View file

@ -901,9 +901,13 @@ impl JsRuntime {
let mut receiver = self.mod_evaluate_inner(id)?;
poll_fn(|cx| {
if let Poll::Ready(result) = receiver.poll_next_unpin(cx) {
debug!("received module evaluate");
return Poll::Ready(result.unwrap());
if let Poll::Ready(maybe_result) = receiver.poll_next_unpin(cx) {
debug!("received module evaluate {:#?}", maybe_result);
// If `None` is returned it means that runtime was destroyed before
// evaluation was complete. This can happen in Web Worker when `self.close()`
// is called at top level.
let result = maybe_result.unwrap_or(Ok(()));
return Poll::Ready(result);
}
let _r = self.poll_event_loop(cx)?;
Poll::Pending