summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiam Murphy <43807659+Liamolucko@users.noreply.github.com>2021-04-20 00:57:02 +1000
committerGitHub <noreply@github.com>2021-04-19 16:57:02 +0200
commit4786e1d92dcbdcbe743c5e2be0878c3c4f68e781 (patch)
tree54dfcfd0b9eab77f45f015e9113b21e2a4884f3e
parent776a999eab2b04385ccd2c80cdce365feec20e05 (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.rs6
-rw-r--r--cli/tests/workers/nonexistent_worker.out3
-rw-r--r--cli/tests/workers/nonexistent_worker.ts5
-rw-r--r--runtime/web_worker.rs8
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(())
}