all: fix memory leaks
This commit is contained in:
parent
e212e0b8b1
commit
9904717c71
18 changed files with 149 additions and 10 deletions
|
|
@ -588,6 +588,9 @@ impl Client {
|
||||||
handler();
|
handler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ServerMessage::Clear => {
|
||||||
|
// only used by test config
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ pub enum ServerMessage {
|
||||||
TimerExpired {
|
TimerExpired {
|
||||||
timer: Timer,
|
timer: Timer,
|
||||||
},
|
},
|
||||||
|
Clear,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, BorrowDecode, Debug)]
|
#[derive(Encode, BorrowDecode, Debug)]
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,14 @@ impl AsyncEngine {
|
||||||
Timer::new(self, clock_id)
|
Timer::new(self, clock_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
for (_, fd) in self.fds.lock().drain() {
|
||||||
|
fd.readers.take();
|
||||||
|
fd.writers.take();
|
||||||
|
}
|
||||||
|
self.queue.clear();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn spawn<T, F: Future<Output = T> + 'static>(&self, f: F) -> SpawnedFuture<T> {
|
pub fn spawn<T, F: Future<Output = T> + 'static>(&self, f: F) -> SpawnedFuture<T> {
|
||||||
self.queue.spawn(Phase::EventHandling, f)
|
self.queue.spawn(Phase::EventHandling, f)
|
||||||
}
|
}
|
||||||
|
|
@ -607,6 +615,13 @@ mod queue {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DispatchQueue {
|
impl DispatchQueue {
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.yields.take();
|
||||||
|
for queue in &self.queues {
|
||||||
|
queue.take();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn push(&self, runnable: Runnable, phase: Phase) {
|
pub fn push(&self, runnable: Runnable, phase: Phase) {
|
||||||
self.queues[phase as usize].push(runnable);
|
self.queues[phase as usize].push(runnable);
|
||||||
self.num_queued.fetch_add(1);
|
self.num_queued.fetch_add(1);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use {
|
||||||
metal, x,
|
metal, x,
|
||||||
},
|
},
|
||||||
cli::{CliBackend, GlobalArgs, RunArgs},
|
cli::{CliBackend, GlobalArgs, RunArgs},
|
||||||
client::Clients,
|
client::{ClientId, Clients},
|
||||||
clientmem::{self, ClientMemError},
|
clientmem::{self, ClientMemError},
|
||||||
config::ConfigProxy,
|
config::ConfigProxy,
|
||||||
dbus::Dbus,
|
dbus::Dbus,
|
||||||
|
|
@ -176,7 +176,9 @@ fn start_compositor2(
|
||||||
run_toplevel,
|
run_toplevel,
|
||||||
config_dir: config_dir(),
|
config_dir: config_dir(),
|
||||||
config_file_id: NumCell::new(1),
|
config_file_id: NumCell::new(1),
|
||||||
|
tracker: Default::default(),
|
||||||
});
|
});
|
||||||
|
state.tracker.register(ClientId::from_raw(0));
|
||||||
create_dummy_output(&state);
|
create_dummy_output(&state);
|
||||||
let acceptor = Acceptor::install(&state)?;
|
let acceptor = Acceptor::install(&state)?;
|
||||||
forker.install(&state);
|
forker.install(&state);
|
||||||
|
|
@ -190,10 +192,14 @@ fn start_compositor2(
|
||||||
let compositor = engine.spawn(start_compositor3(state.clone(), test_future));
|
let compositor = engine.spawn(start_compositor3(state.clone(), test_future));
|
||||||
el.run()?;
|
el.run()?;
|
||||||
drop(compositor);
|
drop(compositor);
|
||||||
|
drop(acceptor);
|
||||||
|
drop(forker);
|
||||||
|
engine.clear();
|
||||||
state.clear();
|
state.clear();
|
||||||
for (_, seat) in state.globals.seats.lock().deref() {
|
for (_, seat) in state.globals.seats.lock().deref() {
|
||||||
seat.clear();
|
seat.clear();
|
||||||
}
|
}
|
||||||
|
drop(state);
|
||||||
leaks::log_leaked();
|
leaks::log_leaked();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,10 @@ impl ConfigProxy {
|
||||||
pub fn graphics_initialized(&self) {
|
pub fn graphics_initialized(&self) {
|
||||||
self.send(&ServerMessage::GraphicsInitialized);
|
self.send(&ServerMessage::GraphicsInitialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.send(&ServerMessage::Clear);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for ConfigProxy {
|
impl Drop for ConfigProxy {
|
||||||
|
|
|
||||||
11
src/dbus.rs
11
src/dbus.rs
|
|
@ -153,6 +153,11 @@ impl Dbus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.system.clear();
|
||||||
|
self.session.clear();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn system(&self) -> Result<Rc<DbusSocket>, DbusError> {
|
pub fn system(&self) -> Result<Rc<DbusSocket>, DbusError> {
|
||||||
self.system
|
self.system
|
||||||
.get(&self.eng, "/var/run/dbus/system_bus_socket", "System bus")
|
.get(&self.eng, "/var/run/dbus/system_bus_socket", "System bus")
|
||||||
|
|
@ -261,6 +266,12 @@ impl DbusHolder {
|
||||||
run_toplevel: run_toplevel.clone(),
|
run_toplevel: run_toplevel.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
if let Some(socket) = self.socket.take() {
|
||||||
|
socket.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for DbusHolder {
|
impl Drop for DbusHolder {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,14 @@ use {
|
||||||
};
|
};
|
||||||
|
|
||||||
impl DbusSocket {
|
impl DbusSocket {
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.auth.take();
|
||||||
|
self.incoming.take();
|
||||||
|
self.outgoing_.take();
|
||||||
|
self.reply_handlers.clear();
|
||||||
|
self.signal_handlers.borrow_mut().clear();
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn kill(self: &Rc<Self>) {
|
pub(super) fn kill(self: &Rc<Self>) {
|
||||||
self.dead.set(true);
|
self.dead.set(true);
|
||||||
self.auth.take();
|
self.auth.take();
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,12 @@ pub enum ForkerError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ForkerProxy {
|
impl ForkerProxy {
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.task_in.take();
|
||||||
|
self.task_out.take();
|
||||||
|
self.task_proc.take();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create() -> Result<Self, ForkerError> {
|
pub fn create() -> Result<Self, ForkerError> {
|
||||||
let (parent, child) = match uapi::socketpair(
|
let (parent, child) = match uapi::socketpair(
|
||||||
c::AF_UNIX,
|
c::AF_UNIX,
|
||||||
|
|
@ -240,8 +246,8 @@ impl ForkerProxy {
|
||||||
}
|
}
|
||||||
if let Err(e) = io.write_msg(msg).await {
|
if let Err(e) = io.write_msg(msg).await {
|
||||||
log::error!("Could not write to the ol' forker: {}", ErrorFmt(e));
|
log::error!("Could not write to the ol' forker: {}", ErrorFmt(e));
|
||||||
|
self.clear();
|
||||||
state.forker.set(None);
|
state.forker.set(None);
|
||||||
self.task_out.take();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -258,9 +264,8 @@ impl ForkerProxy {
|
||||||
let _ = uapi::waitpid(self.pid, 0);
|
let _ = uapi::waitpid(self.pid, 0);
|
||||||
}
|
}
|
||||||
log::error!("The ol' forker died. Cannot spawn further processes.");
|
log::error!("The ol' forker died. Cannot spawn further processes.");
|
||||||
|
self.clear();
|
||||||
state.forker.set(None);
|
state.forker.set(None);
|
||||||
self.task_out.take();
|
|
||||||
self.task_proc.take();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,12 @@ impl Globals {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.registry.clear();
|
||||||
|
self.outputs.clear();
|
||||||
|
self.seats.clear();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_singletons(&self, backend: &Rc<dyn Backend>) {
|
pub fn add_singletons(&self, backend: &Rc<dyn Backend>) {
|
||||||
macro_rules! add_singleton {
|
macro_rules! add_singleton {
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,11 @@ pub struct WlOutputGlobal {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WlOutputGlobal {
|
impl WlOutputGlobal {
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.node.take();
|
||||||
|
self.bindings.borrow_mut().clear();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
name: GlobalName,
|
name: GlobalName,
|
||||||
state: &Rc<State>,
|
state: &Rc<State>,
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ unsafe extern "C" fn unref(data: *const u8) {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn handle_msg(data: *const u8, msg: *const u8, size: usize) {
|
unsafe extern "C" fn handle_msg(data: *const u8, msg: *const u8, size: usize) {
|
||||||
let _tc = &*data.cast::<TestConfig>();
|
let tc = &*data.cast::<TestConfig>();
|
||||||
let msg = std::slice::from_raw_parts(msg, size);
|
let msg = std::slice::from_raw_parts(msg, size);
|
||||||
let res = bincode::decode_from_slice::<ServerMessage, _>(msg, bincode_ops());
|
let res = bincode::decode_from_slice::<ServerMessage, _>(msg, bincode_ops());
|
||||||
let (msg, _) = match res {
|
let (msg, _) = match res {
|
||||||
|
|
@ -83,6 +83,7 @@ unsafe extern "C" fn handle_msg(data: *const u8, msg: *const u8, size: usize) {
|
||||||
ServerMessage::DelConnector { .. } => {}
|
ServerMessage::DelConnector { .. } => {}
|
||||||
ServerMessage::TimerExpired { .. } => {}
|
ServerMessage::TimerExpired { .. } => {}
|
||||||
ServerMessage::GraphicsInitialized => {}
|
ServerMessage::GraphicsInitialized => {}
|
||||||
|
ServerMessage::Clear => tc.clear(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,10 +115,8 @@ impl TestConfig {
|
||||||
pub fn quit(&self) -> Result<(), TestError> {
|
pub fn quit(&self) -> Result<(), TestError> {
|
||||||
self.send(ClientMessage::Quit)
|
self.send(ClientMessage::Quit)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for TestConfig {
|
fn clear(&self) {
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(srv) = self.srv.take() {
|
if let Some(srv) = self.srv.take() {
|
||||||
(srv.srv_unref)(srv.srv_data);
|
(srv.srv_unref)(srv.srv_data);
|
||||||
|
|
@ -125,3 +124,9 @@ impl Drop for TestConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for TestConfig {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
41
src/state.rs
41
src/state.rs
|
|
@ -22,6 +22,7 @@ use {
|
||||||
NoneSurfaceExt,
|
NoneSurfaceExt,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
leaks::Tracker,
|
||||||
logger::Logger,
|
logger::Logger,
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
render::RenderContext,
|
render::RenderContext,
|
||||||
|
|
@ -99,8 +100,15 @@ pub struct State {
|
||||||
pub run_toplevel: Rc<RunToplevel>,
|
pub run_toplevel: Rc<RunToplevel>,
|
||||||
pub config_dir: Option<String>,
|
pub config_dir: Option<String>,
|
||||||
pub config_file_id: NumCell<u64>,
|
pub config_file_id: NumCell<u64>,
|
||||||
|
pub tracker: Tracker<Self>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// impl Drop for State {
|
||||||
|
// fn drop(&mut self) {
|
||||||
|
// log::info!("drop state");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
impl Debug for State {
|
impl Debug for State {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("State").finish_non_exhaustive()
|
f.debug_struct("State").finish_non_exhaustive()
|
||||||
|
|
@ -408,8 +416,39 @@ impl State {
|
||||||
pub fn clear(&self) {
|
pub fn clear(&self) {
|
||||||
self.xwayland.handler.borrow_mut().take();
|
self.xwayland.handler.borrow_mut().take();
|
||||||
self.clients.clear();
|
self.clients.clear();
|
||||||
self.config.set(None);
|
if let Some(config) = self.config.set(None) {
|
||||||
|
config.clear();
|
||||||
|
}
|
||||||
|
if let Some(forker) = self.forker.set(None) {
|
||||||
|
forker.clear();
|
||||||
|
}
|
||||||
|
if let Some(output) = self.dummy_output.set(None) {
|
||||||
|
output.clear();
|
||||||
|
}
|
||||||
|
self.acceptor.set(None);
|
||||||
self.backend.set(Rc::new(DummyBackend));
|
self.backend.set(Rc::new(DummyBackend));
|
||||||
|
self.run_toplevel.clear();
|
||||||
|
self.xwayland.handler.borrow_mut().take();
|
||||||
|
self.xwayland.queue.clear();
|
||||||
|
self.idle.inhibitors.clear();
|
||||||
|
for (_, connector) in self.connectors.lock().drain() {
|
||||||
|
connector.handler.take();
|
||||||
|
}
|
||||||
|
for (_, output) in self.outputs.lock().drain() {
|
||||||
|
output.node.clear();
|
||||||
|
}
|
||||||
|
self.dbus.clear();
|
||||||
|
self.pending_container_layout.clear();
|
||||||
|
self.pending_container_render_data.clear();
|
||||||
|
self.pending_float_layout.clear();
|
||||||
|
self.pending_float_titles.clear();
|
||||||
|
self.slow_clients.clear();
|
||||||
|
self.input_device_handlers.borrow_mut().clear();
|
||||||
|
self.backend_events.clear();
|
||||||
|
self.workspaces.clear();
|
||||||
|
self.globals.clear();
|
||||||
|
self.render_ctx.set(None);
|
||||||
|
self.root.clear();
|
||||||
{
|
{
|
||||||
let seats = mem::take(self.globals.seats.lock().deref_mut());
|
let seats = mem::take(self.globals.seats.lock().deref_mut());
|
||||||
for seat in seats.values() {
|
for seat in seats.values() {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,9 @@ pub fn handle(state: &Rc<State>, connector: &Rc<dyn Connector>) {
|
||||||
};
|
};
|
||||||
let future = state.eng.spawn(oh.handle());
|
let future = state.eng.spawn(oh.handle());
|
||||||
data.handler.set(Some(future));
|
data.handler.set(Some(future));
|
||||||
state.connectors.set(id, data);
|
if state.connectors.set(id, data).is_some() {
|
||||||
|
panic!("Connector id has been reused");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ConnectorHandler {
|
struct ConnectorHandler {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,10 @@ impl DisplayNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.outputs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_extents(&self) {
|
pub fn update_extents(&self) {
|
||||||
let outputs = self.outputs.lock();
|
let outputs = self.outputs.lock();
|
||||||
let mut x1 = i32::MAX;
|
let mut x1 = i32::MAX;
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,15 @@ pub struct OutputNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OutputNode {
|
impl OutputNode {
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.global.clear();
|
||||||
|
self.workspace.set(None);
|
||||||
|
let workspaces: Vec<_> = self.workspaces.iter().collect();
|
||||||
|
for workspace in workspaces {
|
||||||
|
workspace.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_render_data(&self) {
|
pub fn update_render_data(&self) {
|
||||||
let mut rd = self.render_data.borrow_mut();
|
let mut rd = self.render_data.borrow_mut();
|
||||||
rd.titles.clear();
|
rd.titles.clear();
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,12 @@ pub struct WorkspaceNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorkspaceNode {
|
impl WorkspaceNode {
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.container.set(None);
|
||||||
|
self.output_link.set(None);
|
||||||
|
self.fullscreen.set(None);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_container(self: &Rc<Self>, container: &Rc<ContainerNode>) {
|
pub fn set_container(self: &Rc<Self>, container: &Rc<ContainerNode>) {
|
||||||
let pos = self.position.get();
|
let pos = self.position.get();
|
||||||
container.clone().tl_change_extents(&pos);
|
container.clone().tl_change_extents(&pos);
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,10 @@ impl RunToplevel {
|
||||||
self.schedule_dyn(Box::new(f));
|
self.schedule_dyn(Box::new(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.queue.clear();
|
||||||
|
}
|
||||||
|
|
||||||
fn schedule_dyn(&self, f: Box<dyn FnOnce()>) {
|
fn schedule_dyn(&self, f: Box<dyn FnOnce()>) {
|
||||||
self.queue.push(f);
|
self.queue.push(f);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,4 +36,10 @@ impl<T> SyncQueue<T> {
|
||||||
mem::swap(self.el.get().deref_mut(), queue);
|
mem::swap(self.el.get().deref_mut(), queue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn take(&self) -> VecDeque<T> {
|
||||||
|
let mut res = VecDeque::new();
|
||||||
|
self.swap(&mut res);
|
||||||
|
res
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue