Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Terminate timer scheduler thread during shutdown #16184

Merged
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -96,7 +96,7 @@ use profile_traits::time;
use script_traits::{AnimationState, AnimationTickType, CompositorEvent};
use script_traits::{ConstellationControlMsg, ConstellationMsg as FromCompositorMsg, DiscardBrowsingContext};
use script_traits::{DocumentActivity, DocumentState, LayoutControlMsg, LoadData};
use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState, TimerEventRequest};
use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState, TimerSchedulerMsg};
use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
use script_traits::{LogEntry, ServiceWorkerMsg, webdriver_msg};
use script_traits::{MozBrowserErrorType, MozBrowserEvent, WebDriverCommandMsg, WindowSizeData};
@@ -214,7 +214,7 @@ pub struct Constellation<Message, LTF, STF> {

/// A channel for the constellation to send messages to the
/// timer thread.
scheduler_chan: IpcSender<TimerEventRequest>,
scheduler_chan: IpcSender<TimerSchedulerMsg>,

/// A channel for the constellation to send messages to the
/// Webrender thread.
@@ -1241,6 +1241,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
}

debug!("Exiting timer scheduler.");
if let Err(e) = self.scheduler_chan.send(TimerSchedulerMsg::Exit) {
warn!("Exit timer scheduler failed ({})", e);
}

debug!("Exiting font cache thread.");
self.font_cache_thread.exit();

@@ -25,7 +25,7 @@ use script_traits::{ConstellationControlMsg, DevicePixel, DiscardBrowsingContext
use script_traits::{DocumentActivity, InitialScriptState};
use script_traits::{LayoutControlMsg, LayoutMsg, LoadData, MozBrowserEvent};
use script_traits::{NewLayoutInfo, SWManagerMsg, SWManagerSenders, ScriptMsg};
use script_traits::{ScriptThreadFactory, TimerEventRequest, WindowSizeData};
use script_traits::{ScriptThreadFactory, TimerSchedulerMsg, WindowSizeData};
use servo_config::opts::{self, Opts};
use servo_config::prefs::{PREFS, Pref};
use servo_url::ServoUrl;
@@ -121,7 +121,7 @@ pub struct InitialPipelineState {
pub layout_to_constellation_chan: IpcSender<LayoutMsg>,

/// A channel to schedule timer events.
pub scheduler_chan: IpcSender<TimerEventRequest>,
pub scheduler_chan: IpcSender<TimerSchedulerMsg>,

/// A channel to the compositor.
pub compositor_proxy: Box<CompositorProxy + 'static + Send>,
@@ -445,7 +445,7 @@ pub struct UnprivilegedPipelineContent {
parent_info: Option<(PipelineId, FrameType)>,
constellation_chan: IpcSender<ScriptMsg>,
layout_to_constellation_chan: IpcSender<LayoutMsg>,
scheduler_chan: IpcSender<TimerEventRequest>,
scheduler_chan: IpcSender<TimerSchedulerMsg>,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
bluetooth_thread: IpcSender<BluetoothRequest>,
swmanager_thread: IpcSender<SWManagerMsg>,
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use ipc_channel::ipc::{self, IpcSender};
use script_traits::{TimerEvent, TimerEventRequest};
use script_traits::{TimerEvent, TimerEventRequest, TimerSchedulerMsg};
use std::cmp::{self, Ord};
use std::collections::BinaryHeap;
use std::sync::mpsc;
@@ -38,7 +38,7 @@ impl PartialEq for ScheduledEvent {
}

impl TimerScheduler {
pub fn start() -> IpcSender<TimerEventRequest> {
pub fn start() -> IpcSender<TimerSchedulerMsg> {
let (req_ipc_sender, req_ipc_receiver) = ipc::channel().expect("Channel creation failed.");
let (req_sender, req_receiver) = mpsc::sync_channel(1);

@@ -72,7 +72,7 @@ impl TimerScheduler {
// Look to see if there are any incoming events
match req_receiver.try_recv() {
// If there is an event, add it to the priority queue
Ok(req) => {
Ok(TimerSchedulerMsg::Request(req)) => {
let TimerEventRequest(_, _, _, delay) = req;
let schedule = Instant::now() + Duration::from_millis(delay.get());
let event = ScheduledEvent { request: req, for_time: schedule };
@@ -85,7 +85,8 @@ impl TimerScheduler {
None => thread::park(),
Some(event) => thread::park_timeout(event.for_time - now),
},
// If the channel is closed, we are done.
// If the channel is closed or we are shutting down, we are done.
Ok(TimerSchedulerMsg::Exit) |
Err(Disconnected) => break,
}
}
@@ -105,8 +106,16 @@ impl TimerScheduler {
.name(String::from("TimerProxy"))
.spawn(move || {
while let Ok(req) = req_ipc_receiver.recv() {
let mut shutting_down = false;
match req {
TimerSchedulerMsg::Exit => shutting_down = true,
_ => {}
}
let _ = req_sender.send(req);
timeout_thread.unpark();
if shutting_down {
break;
}
}
// This thread can terminate if the req_ipc_sender is dropped.
warn!("TimerProxy thread terminated.");
@@ -37,7 +37,7 @@ use profile_traits::{mem, time};
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
use script_thread::{MainThreadScriptChan, RunnableWrapper, ScriptThread};
use script_traits::{MsDuration, ScriptMsg as ConstellationMsg, TimerEvent};
use script_traits::{TimerEventId, TimerEventRequest, TimerSource};
use script_traits::{TimerEventId, TimerSchedulerMsg, TimerSource};
use servo_url::ServoUrl;
use std::cell::Cell;
use std::collections::HashMap;
@@ -82,7 +82,7 @@ pub struct GlobalScope {
constellation_chan: IpcSender<ConstellationMsg>,

#[ignore_heap_size_of = "channels are hard"]
scheduler_chan: IpcSender<TimerEventRequest>,
scheduler_chan: IpcSender<TimerSchedulerMsg>,

/// https://html.spec.whatwg.org/multipage/#in-error-reporting-mode
in_error_reporting_mode: Cell<bool>,
@@ -101,7 +101,7 @@ impl GlobalScope {
mem_profiler_chan: mem::ProfilerChan,
time_profiler_chan: time::ProfilerChan,
constellation_chan: IpcSender<ConstellationMsg>,
scheduler_chan: IpcSender<TimerEventRequest>,
scheduler_chan: IpcSender<TimerSchedulerMsg>,
resource_threads: ResourceThreads,
timer_event_chan: IpcSender<TimerEvent>)
-> Self {
@@ -229,7 +229,7 @@ impl GlobalScope {
&self.constellation_chan
}

pub fn scheduler_chan(&self) -> &IpcSender<TimerEventRequest> {
pub fn scheduler_chan(&self) -> &IpcSender<TimerSchedulerMsg> {
&self.scheduler_chan
}

@@ -80,7 +80,7 @@ use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, Runnabl
use script_thread::{SendableMainThreadScriptChan, ImageCacheMsg};
use script_traits::{ConstellationControlMsg, LoadData, MozBrowserEvent, UntrustedNodeAddress};
use script_traits::{DocumentState, TimerEvent, TimerEventId};
use script_traits::{ScriptMsg as ConstellationMsg, TimerEventRequest, WindowSizeData, WindowSizeType};
use script_traits::{ScriptMsg as ConstellationMsg, TimerSchedulerMsg, WindowSizeData, WindowSizeType};
use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
use servo_atoms::Atom;
use servo_config::opts;
@@ -1711,7 +1711,7 @@ impl Window {
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
constellation_chan: IpcSender<ConstellationMsg>,
control_chan: IpcSender<ConstellationControlMsg>,
scheduler_chan: IpcSender<TimerEventRequest>,
scheduler_chan: IpcSender<TimerSchedulerMsg>,
timer_event_chan: IpcSender<TimerEvent>,
layout_chan: Sender<Msg>,
id: PipelineId,
@@ -86,7 +86,7 @@ use script_traits::{CompositorEvent, ConstellationControlMsg};
use script_traits::{DocumentActivity, DiscardBrowsingContext, EventResult};
use script_traits::{InitialScriptState, LayoutMsg, LoadData, MouseButton, MouseEventType, MozBrowserEvent};
use script_traits::{NewLayoutInfo, ScriptMsg as ConstellationMsg};
use script_traits::{ScriptThreadFactory, TimerEvent, TimerEventRequest, TimerSource};
use script_traits::{ScriptThreadFactory, TimerEvent, TimerSchedulerMsg, TimerSource};
use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent};
use script_traits::CompositorEvent::{TouchEvent, TouchpadPressureEvent};
@@ -472,7 +472,7 @@ pub struct ScriptThread {
/// List of pipelines that have been owned and closed by this script thread.
closed_pipelines: DOMRefCell<HashSet<PipelineId>>,

scheduler_chan: IpcSender<TimerEventRequest>,
scheduler_chan: IpcSender<TimerSchedulerMsg>,
timer_event_chan: Sender<TimerEvent>,
timer_event_port: Receiver<TimerEvent>,

@@ -18,7 +18,8 @@ use ipc_channel::ipc::IpcSender;
use js::jsapi::{HandleValue, Heap};
use js::jsval::{JSVal, UndefinedValue};
use script_traits::{MsDuration, precise_time_ms};
use script_traits::{TimerEvent, TimerEventId, TimerEventRequest, TimerSource};
use script_traits::{TimerEvent, TimerEventId, TimerEventRequest};
use script_traits::{TimerSchedulerMsg, TimerSource};
use servo_config::prefs::PREFS;
use std::cell::Cell;
use std::cmp::{self, Ord, Ordering};
@@ -35,7 +36,7 @@ pub struct OneshotTimers {
#[ignore_heap_size_of = "Defined in std"]
timer_event_chan: IpcSender<TimerEvent>,
#[ignore_heap_size_of = "Defined in std"]
scheduler_chan: IpcSender<TimerEventRequest>,
scheduler_chan: IpcSender<TimerSchedulerMsg>,
next_timer_handle: Cell<OneshotTimerHandle>,
timers: DOMRefCell<Vec<OneshotTimer>>,
suspended_since: Cell<Option<MsDuration>>,
@@ -109,7 +110,7 @@ impl PartialEq for OneshotTimer {

impl OneshotTimers {
pub fn new(timer_event_chan: IpcSender<TimerEvent>,
scheduler_chan: IpcSender<TimerEventRequest>)
scheduler_chan: IpcSender<TimerSchedulerMsg>)
-> OneshotTimers {
OneshotTimers {
js_timers: JsTimers::new(),
@@ -267,7 +268,7 @@ impl OneshotTimers {
let delay = Length::new(timer.scheduled_for.get().saturating_sub(precise_time_ms().get()));
let request = TimerEventRequest(self.timer_event_chan.clone(), timer.source,
expected_event_id, delay);
self.scheduler_chan.send(request).unwrap();
self.scheduler_chan.send(TimerSchedulerMsg::Request(request)).unwrap();
}
}

@@ -416,6 +416,15 @@ pub enum TouchpadPressurePhase {
#[derive(Deserialize, Serialize)]
pub struct TimerEventRequest(pub IpcSender<TimerEvent>, pub TimerSource, pub TimerEventId, pub MsDuration);

/// Type of messages that can be sent to the timer scheduler.
#[derive(Deserialize, Serialize)]
pub enum TimerSchedulerMsg {
/// Message to schedule a new timer event.
Request(TimerEventRequest),
/// Message to exit the timer scheduler.
Exit,
}

/// Notifies the script thread to fire due timers.
/// `TimerSource` must be `FromWindow` when dispatched to `ScriptThread` and
/// must be `FromWorker` when dispatched to a `DedicatedGlobalWorkerScope`
@@ -479,7 +488,7 @@ pub struct InitialScriptState {
/// A sender for the layout thread to communicate to the constellation.
pub layout_to_constellation_chan: IpcSender<LayoutMsg>,
/// A channel to schedule timer events.
pub scheduler_chan: IpcSender<TimerEventRequest>,
pub scheduler_chan: IpcSender<TimerSchedulerMsg>,
/// A channel to the resource manager thread.
pub resource_threads: ResourceThreads,
/// A channel to the bluetooth thread.
@@ -770,7 +779,7 @@ pub struct WorkerGlobalScopeInit {
/// Messages to send to constellation
pub constellation_chan: IpcSender<ScriptMsg>,
/// Message to send to the scheduler
pub scheduler_chan: IpcSender<TimerEventRequest>,
pub scheduler_chan: IpcSender<TimerSchedulerMsg>,
/// The worker id
pub worker_id: WorkerId,
/// The pipeline id
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.