summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSebastian Holmin <sebastian.holmin@mullvad.net>2026-02-10 09:42:41 +0100
committerSebastian Holmin <sebastian.holmin@mullvad.net>2026-02-10 09:42:41 +0100
commite8ce8e080877e3fee1970d66e4b1936e219784d3 (patch)
tree36becdb0ae1d20c6184c0e2f88ba25a71bc7d2a5
parentca121961b549ca72e3c959a5951135e216a281cc (diff)
parentf0c6b199e494dfd8b0726a98014751e57cc31330 (diff)
downloadmullvadvpn-test-broken-ci.tar.xz
mullvadvpn-test-broken-ci.zip
Merge branch 'early-boot-fwlog-doesnt-flush-des-2834'test-broken-ci
-rw-r--r--mullvad-daemon/src/logging.rs37
-rw-r--r--mullvad-daemon/src/main.rs26
2 files changed, 34 insertions, 29 deletions
diff --git a/mullvad-daemon/src/logging.rs b/mullvad-daemon/src/logging.rs
index 2b97d2d2ab..156ba31fb0 100644
--- a/mullvad-daemon/src/logging.rs
+++ b/mullvad-daemon/src/logging.rs
@@ -2,10 +2,7 @@ use mullvad_logging::{EnvFilter, LevelFilter, silence_crates};
use std::{
io,
path::PathBuf,
- sync::{
- Arc,
- atomic::{AtomicBool, Ordering},
- },
+ sync::atomic::{AtomicBool, Ordering},
};
use talpid_core::logging::rotate_log;
use tracing_appender::non_blocking;
@@ -56,11 +53,12 @@ pub fn is_enabled() -> bool {
LOG_ENABLED.load(Ordering::SeqCst)
}
+/// Handle to interact with the logs. Use it to change the log level at runtime or
+/// to receive a stream of logs.
#[derive(Clone)]
pub struct LogHandle {
env_filter: Handle<EnvFilter, Registry>,
log_stream: LogStreamer,
- _file_appender_guard: Option<Arc<non_blocking::WorkerGuard>>,
}
/// A location to put logs.
@@ -159,17 +157,23 @@ pub fn init_logger(
let default_filter = silence_crates(env_filter);
// TODO: Switch this to a rolling appender, likely daily or hourly
- let (_file_appender_guard, non_blocking_file_appender) =
- if let Some(log_location) = log_location.as_ref() {
- // NOTE: Make sure to rotate log file *before* initializing any kind of logger.
- rotate_log(&log_location.log_path()).map_err(Error::RotateLog)?;
- let file_appender =
- tracing_appender::rolling::never(&log_location.directory, &log_location.filename);
- let (appender, guard) = non_blocking(file_appender);
- (Some(Arc::new(guard)), OptionalMakeWriter(Some(appender)))
- } else {
- (None, OptionalMakeWriter(None))
- };
+ let non_blocking_file_appender = if let Some(log_location) = log_location.as_ref() {
+ // NOTE: Make sure to rotate log file *before* initializing any kind of logger.
+ rotate_log(&log_location.log_path()).map_err(Error::RotateLog)?;
+ let file_appender =
+ tracing_appender::rolling::never(&log_location.directory, &log_location.filename);
+ let (appender, guard) = non_blocking(file_appender);
+ // Spawn a task to keep file logger guard alive for the duration of the program. When the tokio
+ // executor shuts down, its drop function will be called to flush any remaining logs to file.
+ // Note that calling e.g. `std::process::exit` will prevent this and might result in lost logs.
+ tokio::spawn(async move {
+ std::future::pending::<()>().await;
+ drop(guard);
+ });
+ OptionalMakeWriter(Some(appender))
+ } else {
+ OptionalMakeWriter(None)
+ };
let (tx, _) = tokio::sync::broadcast::channel(128);
let log_stream = LogStreamer { tx };
@@ -178,7 +182,6 @@ pub fn init_logger(
let reload_handle = LogHandle {
env_filter: reload_handle,
log_stream: log_stream.clone(),
- _file_appender_guard,
};
let reg = tracing_subscriber::registry().with(user_filter);
diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs
index bbc99ca7ee..4a87f976c4 100644
--- a/mullvad-daemon/src/main.rs
+++ b/mullvad-daemon/src/main.rs
@@ -35,7 +35,8 @@ fn main() {
}
};
- log::debug!("Process exiting with code {}", exit_code);
+ log::debug!("Process exiting with code {exit_code}");
+ runtime.shutdown_timeout(Duration::from_millis(100));
std::process::exit(exit_code);
}
@@ -57,14 +58,14 @@ async fn run() -> Result<(), String> {
match config.command {
cli::Command::Daemon => {
- // uniqueness check must happen before logging initializaton,
+ // uniqueness check must happen before logging initialization,
// as initializing logs will rotate any existing log file.
assert_unique().await?;
- let (log_location, reload_handle) = init_daemon_logging(config)?;
+ let (log_location, log_handle) = init_daemon_logging(config)?;
log::trace!("Using configuration: {:?}", config);
let log_dir = log_location.map(|l| l.directory);
- run_standalone(log_dir, reload_handle).await
+ run_standalone(log_dir, log_handle).await
}
#[cfg(target_os = "linux")]
@@ -118,18 +119,18 @@ fn init_daemon_logging(
filename: PathBuf::from("daemon.log"),
});
- let reload_handle = init_logger(config, log_location.clone())?;
+ let log_handle = init_logger(config, log_location.clone())?;
if let Some(log_location) = log_location.as_ref() {
log::info!("Logging to {}", log_location.log_path().display());
}
- Ok((log_location, reload_handle))
+ Ok((log_location, log_handle))
}
-/// Initialize logging to stder and to the [`EARLY_BOOT_LOG_FILENAME`]
+/// Initialize logging to stderr and to the [`EARLY_BOOT_LOG_FILENAME`]
#[cfg(target_os = "linux")]
fn init_early_boot_logging(config: &cli::Config) {
- let logging = get_log_dir(config)
+ let log_file_location = get_log_dir(config)
.ok()
.flatten()
.map(|log_dir| LogLocation {
@@ -139,9 +140,10 @@ fn init_early_boot_logging(config: &cli::Config) {
// If it's possible to log to the filesystem - attempt to do so, but failing that mustn't stop
// the daemon from starting here.
- if init_logger(config, logging).is_err() {
+ if let Err(e) = init_logger(config, log_file_location) {
+ eprintln!("Failed to initialize early-boot logging to file: '{e}'");
let _ = init_logger(config, None);
- };
+ }
}
/// Initialize logging to stderr and to file (if provided).
@@ -163,12 +165,12 @@ fn init_logger(
exception_logging::enable();
- let reload_handle =
+ let log_handle =
logging::init_logger(config.log_level, log_location, config.log_stdout_timestamps)
.map_err(|e| e.display_chain_with_msg("Unable to initialize logger"))?;
log_panics::init();
version::log_version();
- Ok(reload_handle)
+ Ok(log_handle)
}
fn get_log_dir(config: &cli::Config) -> Result<Option<PathBuf>, String> {