diff options
author | Liam Murphy <43807659+Liamolucko@users.noreply.github.com> | 2021-04-20 00:57:02 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-19 16:57:02 +0200 |
commit | 4786e1d92dcbdcbe743c5e2be0878c3c4f68e781 (patch) | |
tree | 54dfcfd0b9eab77f45f015e9113b21e2a4884f3e | |
parent | 776a999eab2b04385ccd2c80cdce365feec20e05 (diff) |
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.
-rw-r--r-- | cli/tests/integration_tests.rs | 6 | ||||
-rw-r--r-- | cli/tests/workers/nonexistent_worker.out | 3 | ||||
-rw-r--r-- | cli/tests/workers/nonexistent_worker.ts | 5 | ||||
-rw-r--r-- | runtime/web_worker.rs | 8 |
4 files changed, 22 insertions, 0 deletions
diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index 1252d8500..d178512c5 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -2497,6 +2497,12 @@ console.log("finish"); exit_code: 1, }); + itest!(nonexistent_worker { + args: "run --allow-read workers/nonexistent_worker.ts", + output: "workers/nonexistent_worker.out", + exit_code: 1, + }); + #[test] fn compiler_api() { let status = util::deno_cmd() diff --git a/cli/tests/workers/nonexistent_worker.out b/cli/tests/workers/nonexistent_worker.out new file mode 100644 index 000000000..e43b81c5f --- /dev/null +++ b/cli/tests/workers/nonexistent_worker.out @@ -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]) diff --git a/cli/tests/workers/nonexistent_worker.ts b/cli/tests/workers/nonexistent_worker.ts new file mode 100644 index 000000000..8ebe29114 --- /dev/null +++ b/cli/tests/workers/nonexistent_worker.ts @@ -0,0 +1,5 @@ +const w = new Worker(new URL("doesnt_exist.js", import.meta.url).href, { + type: "module", +}); + +w.postMessage("hello"); diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index 68bbe1a5d..8c8761d62 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -67,6 +67,14 @@ impl WebWorkerHandle { /// Post message to worker as a host. pub fn post_message(&self, buf: Box<[u8]>) -> Result<(), AnyError> { 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)?; Ok(()) } |