1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 23:34:47 -05:00

fix(runtime): handle race condition in postMessage where worker has terminated (#10239)

The panic was caused by the lack of an error class mapping for
futures::channel::TrySendError, but it shouldn't have been throwing an error in
the first place - when a worker has terminated, postMessage should just return.
The issue was that the termination message hadn't yet been recieved, so it was
carrying on with trying to send the message. This adds another check on the Rust
side for if the channel is closed, and if it is the worker is treated as
terminated.
This commit is contained in:
Liam Murphy 2021-04-20 00:57:02 +10:00 committed by GitHub
parent 776a999eab
commit 4786e1d92d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 22 additions and 0 deletions

View file

@ -2497,6 +2497,12 @@ console.log("finish");
exit_code: 1, exit_code: 1,
}); });
itest!(nonexistent_worker {
args: "run --allow-read workers/nonexistent_worker.ts",
output: "workers/nonexistent_worker.out",
exit_code: 1,
});
#[test] #[test]
fn compiler_api() { fn compiler_api() {
let status = util::deno_cmd() let status = util::deno_cmd()

View file

@ -0,0 +1,3 @@
[WILDCARD]error: Uncaught (in worker "") Cannot resolve module "file:///[WILDCARD]cli/tests/workers/doesnt_exist.js".
error: Uncaught (in promise) Error: Unhandled error event reached main worker.
at Worker.#poll ([WILDCARD])

View file

@ -0,0 +1,5 @@
const w = new Worker(new URL("doesnt_exist.js", import.meta.url).href, {
type: "module",
});
w.postMessage("hello");

View file

@ -67,6 +67,14 @@ impl WebWorkerHandle {
/// Post message to worker as a host. /// Post message to worker as a host.
pub fn post_message(&self, buf: Box<[u8]>) -> Result<(), AnyError> { pub fn post_message(&self, buf: Box<[u8]>) -> Result<(), AnyError> {
let mut sender = self.sender.clone(); let mut sender = self.sender.clone();
// If the channel is closed,
// the worker must have terminated but the termination message has not yet been recieved.
//
// Therefore just treat it as if the worker has terminated and return.
if sender.is_closed() {
self.terminated.store(true, Ordering::SeqCst);
return Ok(());
}
sender.try_send(buf)?; sender.try_send(buf)?;
Ok(()) Ok(())
} }