mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
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.
This commit is contained in:
parent
f7630dad87
commit
b3e85472ed
1 changed files with 26 additions and 4 deletions
|
@ -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.
|
/// A guid for worklets.
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, PartialEq)]
|
||||||
pub struct WorkletId(Uuid);
|
pub struct WorkletId(Uuid);
|
||||||
|
@ -301,10 +308,14 @@ impl WorkletThreadPool {
|
||||||
promise: TrustedPromise::new(promise.clone()),
|
promise: TrustedPromise::new(promise.clone()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// If any of the threads are blocked waiting on data, wake them up.
|
self.wake_threads();
|
||||||
let _ = self.cold_backup_sender.send(WorkletData::WakeUp);
|
}
|
||||||
let _ = self.hot_backup_sender.send(WorkletData::WakeUp);
|
|
||||||
let _ = self.primary_sender.send(WorkletData::WakeUp);
|
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.
|
/// For testing.
|
||||||
|
@ -314,6 +325,13 @@ impl WorkletThreadPool {
|
||||||
let _ = self.primary_sender.send(msg);
|
let _ = self.primary_sender.send(msg);
|
||||||
receiver.recv().expect("Test worklet has died?")
|
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
|
/// The data messages sent to worklet threads
|
||||||
|
@ -327,6 +345,7 @@ enum WorkletData {
|
||||||
|
|
||||||
/// The control message sent to worklet threads
|
/// The control message sent to worklet threads
|
||||||
enum WorkletControl {
|
enum WorkletControl {
|
||||||
|
ExitWorklet(WorkletId),
|
||||||
FetchAndInvokeAWorkletScript {
|
FetchAndInvokeAWorkletScript {
|
||||||
pipeline_id: PipelineId,
|
pipeline_id: PipelineId,
|
||||||
worklet_id: WorkletId,
|
worklet_id: WorkletId,
|
||||||
|
@ -621,6 +640,9 @@ impl WorkletThread {
|
||||||
/// Process a control message.
|
/// Process a control message.
|
||||||
fn process_control(&mut self, control: WorkletControl) {
|
fn process_control(&mut self, control: WorkletControl) {
|
||||||
match control {
|
match control {
|
||||||
|
WorkletControl::ExitWorklet(worklet_id) => {
|
||||||
|
self.global_scopes.remove(&worklet_id);
|
||||||
|
},
|
||||||
WorkletControl::FetchAndInvokeAWorkletScript {
|
WorkletControl::FetchAndInvokeAWorkletScript {
|
||||||
pipeline_id, worklet_id, global_type, origin, base_url,
|
pipeline_id, worklet_id, global_type, origin, base_url,
|
||||||
script_url, credentials, pending_tasks_struct, promise,
|
script_url, credentials, pending_tasks_struct, promise,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue