aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/worklet.rs
diff options
context:
space:
mode:
authorAgustin Chiappe Berrini <jnieve@gmail.com>2018-09-08 18:02:00 -0400
committerAgustin Chiappe Berrini <jnieve@gmail.com>2018-09-08 18:04:31 -0400
commitb3e85472eda2a017334a9faa3b33a3b4e0184e53 (patch)
tree42b980d4964fa6a267466cb3dba660f72390e216 /components/script/dom/worklet.rs
parentf7630dad87da33449ce05b5e7a9ef6f747e9531d (diff)
downloadservo-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.rs30
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,