From 8bff06e9a7409b9f2910c935b3baa059469c11d4 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Thu, 29 Jun 2023 16:39:24 -0400 Subject: [PATCH] wip: better handling of cloexec with reused fds for panel and notifications daemon --- Cargo.lock | 32 ++++-------------- Cargo.toml | 16 +++++++-- src/main.rs | 89 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/process.rs | 15 +++++++++ 4 files changed, 122 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce558f9..6517331 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -458,15 +458,6 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.1" @@ -510,7 +501,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi", "libc", "windows-sys", ] @@ -524,7 +515,7 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "launch-pad" version = "0.1.0" -source = "git+https://github.com/pop-os/launch-pad#943e112ce381b4aef94ed3dba68f0dd2ed6c19ec" +source = "git+https://github.com/pop-os/launch-pad?branch=stdin-msg#6c27271f05f19d0cb8801717c218540f9ed00b3b" dependencies = [ "log", "slotmap", @@ -656,16 +647,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num_cpus" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" -dependencies = [ - "hermit-abi 0.2.6", - "libc", -] - [[package]] name = "object" version = "0.30.4" @@ -787,9 +768,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ "proc-macro2", ] @@ -1131,7 +1112,6 @@ dependencies = [ "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -1337,9 +1317,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", diff --git a/Cargo.toml b/Cargo.toml index 2a7d627..0c702b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ publish = false async-signals = "0.4" color-eyre = "0.6" futures-util = "0.3" -launch-pad = { git = "https://github.com/pop-os/launch-pad" } +launch-pad = { git = "https://github.com/pop-os/launch-pad", branch = "stdin-msg" } libc = "0.2" log-panics = { version = "2", features = ["with-backtrace"] } nix = { version = "0.25", features = ["fs"], default-features = false } @@ -20,7 +20,19 @@ sendfd = { version = "0.4", features = ["tokio"] } serde = { version = "1", features = ["derive"] } serde_json = "1" systemd_client = "0.2" -tokio = { version = "1", features = ["full"] } +tokio = { version = "1", features = [ + "fs", + "io-util", + "io-std", + "macros", + "net", + "parking_lot", + "process", + "rt", + "signal", + "sync", + "time", +] } tokio-util = "0.7" tracing = "0.1" tracing-journald = "0.3" diff --git a/src/main.rs b/src/main.rs index 452f1c6..4a50c56 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,11 @@ mod process; mod service; mod systemd; -use std::os::fd::AsRawFd; +use std::{ + ops::Deref, + os::fd::AsRawFd, + sync::{Arc, Mutex}, +}; use async_signals::Signals; use color_eyre::{eyre::WrapErr, Result}; @@ -24,6 +28,8 @@ use tracing::{metadata::LevelFilter, Instrument}; use tracing_subscriber::{fmt, prelude::*, EnvFilter}; use zbus::ConnectionBuilder; +use crate::process::{mark_as_cloexec, mark_as_not_cloexec}; + #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { color_eyre::install().wrap_err("failed to install color_eyre error handler")?; @@ -75,10 +81,43 @@ async fn main() -> Result<()> { panel_notifications_fd.as_raw_fd().to_string(), )); + let panel_notifications_fd_pre = Arc::new(Mutex::new(panel_notifications_fd)); + let panel_notifications_fd_post = panel_notifications_fd_pre.clone(); + let span = info_span!(parent: None, "cosmic-panel"); + let stdout_span = span.clone(); + let stderr_span = span; process_manager .start( Process::new() .with_executable("cosmic-panel") + .with_pre_start(move |_, _, _| { + let panel_notifications_fd = panel_notifications_fd_pre.clone(); + let fd = panel_notifications_fd.lock().unwrap(); + let fd = fd.deref(); + mark_as_not_cloexec(&fd) + .expect("Failed to mark panel notifications socket as not CLOEXEC"); + }) + .with_post_start(move |_, _, _| { + let panel_notifications_fd = panel_notifications_fd_post.clone(); + let fd = panel_notifications_fd.lock().unwrap(); + let fd = fd.deref(); + mark_as_cloexec(&fd) + .expect("Failed to mark panel notifications socket as CLOEXEC"); + }) + .with_on_stdout(move |_, _, line| { + let stdout_span = stdout_span.clone(); + async move { + info!("{}", line); + } + .instrument(stdout_span) + }) + .with_on_stderr(move |_, _, line| { + let stderr_span = stderr_span.clone(); + async move { + warn!("{}", line); + } + .instrument(stderr_span) + }) .with_env(panel_env_vars.clone()), ) .await @@ -90,7 +129,53 @@ async fn main() -> Result<()> { daemon_notifications_fd.as_raw_fd().to_string(), )); let span = info_span!(parent: None, "cosmic-notifications"); - start_component("cosmic-notifications", span, &process_manager, &env_vars).await; + let stdout_span = span.clone(); + let stderr_span = span; + let daemon_notifications_fd_pre = Arc::new(Mutex::new(daemon_notifications_fd)); + let daemon_notifications_fd_post = daemon_notifications_fd_pre.clone(); + + process_manager + .start( + Process::new() + .with_executable("cosmic-notifications") + .with_pre_start(move |_, _, _| { + let daemon_notifications_fd = daemon_notifications_fd_pre.clone(); + let fd = daemon_notifications_fd.lock().unwrap(); + let fd = fd.deref(); + mark_as_not_cloexec(&fd) + .expect("Failed to mark daemon notifications socket as not CLOEXEC"); + }) + .with_post_start(move |_, _, _| { + let daemon_notifications_fd = daemon_notifications_fd_post.clone(); + let fd = daemon_notifications_fd.lock().unwrap(); + let fd = fd.deref(); + mark_as_cloexec(&fd) + .expect("Failed to mark daemon notifications socket as CLOEXEC"); + }) + .with_on_stdout(move |_, _, line| { + let stdout_span = stdout_span.clone(); + async move { + info!("{}", line); + } + .instrument(stdout_span) + }) + .with_on_stderr(move |_, _, line| { + let stderr_span = stderr_span.clone(); + async move { + warn!("{}", line); + } + .instrument(stderr_span) + }) + .with_env(daemon_env_vars.clone()), + ) + .await + .expect("failed to start notifications daemon"); + + // mark_as_cloexec(&daemon_notifications_fd) + // .expect("Failed to mark daemon notifications socket as CLOEXEC"); + // start_component("cosmic-notifications", span, &process_manager, &env_vars).await; + // mark_as_not_cloexec(&daemon_notifications_fd) + // .expect("Failed to mark daemon notifications socket as not CLOEXEC"); let span = info_span!(parent: None, "cosmic-app-library"); start_component("cosmic-app-library", span, &process_manager, &env_vars).await; diff --git a/src/process.rs b/src/process.rs index 7f381e9..9736e36 100644 --- a/src/process.rs +++ b/src/process.rs @@ -17,3 +17,18 @@ pub(crate) fn mark_as_not_cloexec(file: &impl AsFd) -> Result<()> { .wrap_err("failed to set CLOEXEC on file")?; Ok(()) } + +pub(crate) fn mark_as_cloexec(file: &impl AsFd) -> Result<()> { + let raw_fd = file.as_fd().as_raw_fd(); + let fd_flags = fcntl::FdFlag::from_bits( + fcntl::fcntl(raw_fd, fcntl::FcntlArg::F_GETFD) + .wrap_err("failed to get GETFD value of stream")?, + ) + .wrap_err("failed to get fd flags from file")?; + fcntl::fcntl( + raw_fd, + fcntl::FcntlArg::F_SETFD(fd_flags.union(fcntl::FdFlag::FD_CLOEXEC)), + ) + .wrap_err("failed to set CLOEXEC on file")?; + Ok(()) +}