diff options
Diffstat (limited to 'runtime/ops/worker_host.rs')
-rw-r--r-- | runtime/ops/worker_host.rs | 48 |
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(); } } } |