diff options
author | Agustin Chiappe Berrini <jnieve@gmail.com> | 2018-09-08 18:02:00 -0400 |
---|---|---|
committer | Agustin Chiappe Berrini <jnieve@gmail.com> | 2018-09-08 18:04:31 -0400 |
commit | b3e85472eda2a017334a9faa3b33a3b4e0184e53 (patch) | |
tree | 42b980d4964fa6a267466cb3dba660f72390e216 /components/script/dom/worklet.rs | |
parent | f7630dad87da33449ce05b5e7a9ef6f747e9531d (diff) | |
download | servo-b3e85472eda2a017334a9faa3b33a3b4e0184e53.tar.gz servo-b3e85472eda2a017334a9faa3b33a3b4e0184e53.zip |
Fix space leak when pipeline is closed
Add a new control message to drop remove worklets.
Implement `Drop` for `Worklet` and get the worklet thread pool. Use that
pool to send `ExitWorklet` to all the threads with the id of the
`Worklet` that it's dropping.
Diffstat (limited to 'components/script/dom/worklet.rs')
-rw-r--r-- | components/script/dom/worklet.rs | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/components/script/dom/worklet.rs b/components/script/dom/worklet.rs index d1b7ba9c44a..68efd51b485 100644 --- a/components/script/dom/worklet.rs +++ b/components/script/dom/worklet.rs @@ -147,6 +147,13 @@ impl WorkletMethods for Worklet { } } +impl Drop for Worklet { + fn drop(&mut self) { + let script_thread = ScriptThread::worklet_thread_pool(); + script_thread.exit_worklet(self.worklet_id); + } +} + /// A guid for worklets. #[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, PartialEq)] pub struct WorkletId(Uuid); @@ -301,10 +308,14 @@ impl WorkletThreadPool { promise: TrustedPromise::new(promise.clone()), }); } - // If any of the threads are blocked waiting on data, wake them up. - let _ = self.cold_backup_sender.send(WorkletData::WakeUp); - let _ = self.hot_backup_sender.send(WorkletData::WakeUp); - let _ = self.primary_sender.send(WorkletData::WakeUp); + self.wake_threads(); + } + + pub(crate) fn exit_worklet(&self, worklet_id: WorkletId) { + for sender in &[&self.control_sender_0, &self.control_sender_1, &self.control_sender_2] { + let _ = sender.send(WorkletControl::ExitWorklet(worklet_id)); + } + self.wake_threads(); } /// For testing. @@ -314,6 +325,13 @@ impl WorkletThreadPool { let _ = self.primary_sender.send(msg); receiver.recv().expect("Test worklet has died?") } + + fn wake_threads(&self) { + // If any of the threads are blocked waiting on data, wake them up. + let _ = self.cold_backup_sender.send(WorkletData::WakeUp); + let _ = self.hot_backup_sender.send(WorkletData::WakeUp); + let _ = self.primary_sender.send(WorkletData::WakeUp); + } } /// The data messages sent to worklet threads @@ -327,6 +345,7 @@ enum WorkletData { /// The control message sent to worklet threads enum WorkletControl { + ExitWorklet(WorkletId), FetchAndInvokeAWorkletScript { pipeline_id: PipelineId, worklet_id: WorkletId, @@ -621,6 +640,9 @@ impl WorkletThread { /// Process a control message. fn process_control(&mut self, control: WorkletControl) { match control { + WorkletControl::ExitWorklet(worklet_id) => { + self.global_scopes.remove(&worklet_id); + }, WorkletControl::FetchAndInvokeAWorkletScript { pipeline_id, worklet_id, global_type, origin, base_url, script_url, credentials, pending_tasks_struct, promise, |