mirror of
https://github.com/denoland/deno.git
synced 2025-01-03 12:58:54 -05:00
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:
parent
28869a632d
commit
22f951aa67
6 changed files with 64 additions and 3 deletions
1
cli/tests/immediately_close_worker.js
Normal file
1
cli/tests/immediately_close_worker.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
self.close();
|
|
@ -3273,6 +3273,11 @@ itest!(ignore_require {
|
||||||
exit_code: 0,
|
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]
|
#[test]
|
||||||
fn cafile_env_fetch() {
|
fn cafile_env_fetch() {
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
|
|
33
cli/tests/no_mem_cache.js
Normal file
33
cli/tests/no_mem_cache.js
Normal 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();
|
2
cli/tests/no_mem_cache.js.out
Normal file
2
cli/tests/no_mem_cache.js.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
hello
|
||||||
|
goodbye
|
|
@ -341,3 +341,19 @@ Deno.test({
|
||||||
w.terminate();
|
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();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
|
@ -901,9 +901,13 @@ impl JsRuntime {
|
||||||
let mut receiver = self.mod_evaluate_inner(id)?;
|
let mut receiver = self.mod_evaluate_inner(id)?;
|
||||||
|
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
if let Poll::Ready(result) = receiver.poll_next_unpin(cx) {
|
if let Poll::Ready(maybe_result) = receiver.poll_next_unpin(cx) {
|
||||||
debug!("received module evaluate");
|
debug!("received module evaluate {:#?}", maybe_result);
|
||||||
return Poll::Ready(result.unwrap());
|
// 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)?;
|
let _r = self.poll_event_loop(cx)?;
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
|
|
Loading…
Reference in a new issue