From 240545282a87307829df1aafe74031a382d1ce33 Mon Sep 17 00:00:00 2001 From: Andreu Botella Date: Sat, 17 Jul 2021 00:51:06 +0200 Subject: fix(workers): silently ignore non-existent worker IDs (#11417) Fixes #11416 --- cli/tests/integration/run_tests.rs | 5 +++++ cli/tests/worker_close_race.js | 14 +++++++++++++ cli/tests/worker_close_race.js.out | 0 cli/tests/workers/close_race_worker.js | 6 ++++++ runtime/ops/worker_host.rs | 36 ++++++++++++++++------------------ 5 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 cli/tests/worker_close_race.js create mode 100644 cli/tests/worker_close_race.js.out create mode 100644 cli/tests/workers/close_race_worker.js diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index 2e2b0400c..08e0c8306 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -1160,6 +1160,11 @@ itest!(worker_event_handler_test { output: "worker_event_handler_test.js.out", }); +itest!(worker_close_race { + args: "run --quiet --reload --allow-read worker_close_race.js", + output: "worker_close_race.js.out", +}); + #[test] fn no_validate_asm() { let output = util::deno_cmd() diff --git a/cli/tests/worker_close_race.js b/cli/tests/worker_close_race.js new file mode 100644 index 000000000..6d5bbe2c3 --- /dev/null +++ b/cli/tests/worker_close_race.js @@ -0,0 +1,14 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +// https://github.com/denoland/deno/issues/11416 +// Test for a race condition between a worker's `close()` and the main thread's +// `Worker.prototype.terminate()`. + +const worker = new Worker( + new URL("./workers/close_race_worker.js", import.meta.url), + { type: "module" }, +); + +worker.onmessage = () => { + worker.terminate(); +}; diff --git a/cli/tests/worker_close_race.js.out b/cli/tests/worker_close_race.js.out new file mode 100644 index 000000000..e69de29bb diff --git a/cli/tests/workers/close_race_worker.js b/cli/tests/workers/close_race_worker.js new file mode 100644 index 000000000..f582a0d99 --- /dev/null +++ b/cli/tests/workers/close_race_worker.js @@ -0,0 +1,6 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +setTimeout(() => { + self.postMessage(""); + self.close(); +}, 500); diff --git a/runtime/ops/worker_host.rs b/runtime/ops/worker_host.rs index 162f9f4f7..2cd9a14ad 100644 --- a/runtime/ops/worker_host.rs +++ b/runtime/ops/worker_host.rs @@ -516,16 +516,16 @@ fn op_host_terminate_worker( id: WorkerId, _: (), ) -> Result<(), AnyError> { - let worker_thread = state - .borrow_mut::() - .remove(&id) - .expect("No worker handle found"); - worker_thread.worker_handle.terminate(); - worker_thread - .join_handle - .join() - .expect("Panic in worker thread") - .expect("Panic in worker event loop"); + if let Some(worker_thread) = state.borrow_mut::().remove(&id) { + worker_thread.worker_handle.terminate(); + worker_thread + .join_handle + .join() + .expect("Panic in worker thread") + .expect("Panic in worker event loop"); + } else { + debug!("tried to terminate non-existent worker {}", id); + } Ok(()) } @@ -602,14 +602,12 @@ fn op_host_post_message( id: WorkerId, data: JsMessageData, ) -> Result<(), AnyError> { - debug!("post message to worker {}", id); - let worker_handle = { - let worker_thread = state - .borrow::() - .get(&id) - .expect("No worker handle found"); - worker_thread.worker_handle.clone() - }; - worker_handle.port.send(state, data)?; + if let Some(worker_thread) = state.borrow::().get(&id) { + debug!("post message to worker {}", id); + let worker_handle = worker_thread.worker_handle.clone(); + worker_handle.port.send(state, data)?; + } else { + debug!("tried to post message to non-existent worker {}", id); + } Ok(()) } -- cgit v1.2.3