summaryrefslogtreecommitdiff
path: root/runtime/ops/worker_host.rs
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/ops/worker_host.rs')
-rw-r--r--runtime/ops/worker_host.rs48
1 files changed, 33 insertions, 15 deletions
diff --git a/runtime/ops/worker_host.rs b/runtime/ops/worker_host.rs
index 829681ab6..f749e495c 100644
--- a/runtime/ops/worker_host.rs
+++ b/runtime/ops/worker_host.rs
@@ -65,7 +65,8 @@ pub type CreateWebWorkerCb = dyn Fn(CreateWebWorkerArgs) -> (WebWorker, Sendable
pub struct CreateWebWorkerCbHolder(Arc<CreateWebWorkerCb>);
pub struct WorkerThread {
- join_handle: JoinHandle<Result<(), AnyError>>,
+ // It's an Option so we can take the value before dropping the WorkerThread.
+ join_handle: Option<JoinHandle<Result<(), AnyError>>>,
worker_handle: WebWorkerHandle,
// A WorkerThread that hasn't been explicitly terminated can only be removed
@@ -75,6 +76,34 @@ pub struct WorkerThread {
message_closed: bool,
}
+impl WorkerThread {
+ fn terminate(mut self) {
+ self.worker_handle.clone().terminate();
+ self
+ .join_handle
+ .take()
+ .unwrap()
+ .join()
+ .expect("Worker thread panicked")
+ .expect("Panic in worker event loop");
+
+ // Optimization so the Drop impl doesn't try to terminate the worker handle
+ // again.
+ self.ctrl_closed = true;
+ self.message_closed = true;
+ }
+}
+
+impl Drop for WorkerThread {
+ fn drop(&mut self) {
+ // If either of the channels is closed, the worker thread has at least
+ // started closing, and its event loop won't start another run.
+ if !(self.ctrl_closed || self.message_closed) {
+ self.worker_handle.clone().terminate();
+ }
+ }
+}
+
pub type WorkersTable = HashMap<WorkerId, WorkerThread>;
pub fn init(create_web_worker_cb: Arc<CreateWebWorkerCb>) -> Extension {
@@ -557,7 +586,7 @@ fn op_create_worker(
let worker_handle = handle_receiver.recv().unwrap()?;
let worker_thread = WorkerThread {
- join_handle,
+ join_handle: Some(join_handle),
worker_handle: worker_handle.into(),
ctrl_closed: false,
message_closed: false,
@@ -578,12 +607,7 @@ fn op_host_terminate_worker(
_: (),
) -> Result<(), AnyError> {
if let Some(worker_thread) = state.borrow_mut::<WorkersTable>().remove(&id) {
- worker_thread.worker_handle.terminate();
- worker_thread
- .join_handle
- .join()
- .expect("Panic in worker thread")
- .expect("Panic in worker event loop");
+ worker_thread.terminate();
} else {
debug!("tried to terminate non-existent worker {}", id);
}
@@ -625,13 +649,7 @@ fn close_channel(
};
if terminate {
- let worker_thread = entry.remove();
- worker_thread.worker_handle.terminate();
- worker_thread
- .join_handle
- .join()
- .expect("Worker thread panicked")
- .expect("Panic in worker event loop");
+ entry.remove().terminate();
}
}
}