From 3618c2fbc14a2d66d269e6026630527f128aaa41 Mon Sep 17 00:00:00 2001 From: Esper Thomson Date: Mon, 30 Sep 2024 17:23:58 -0400 Subject: [PATCH] Fix log interleaving when logging from multiple threads. --- astro_modloader/src/logging.rs | 45 ++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/astro_modloader/src/logging.rs b/astro_modloader/src/logging.rs index 16ece28..892269e 100644 --- a/astro_modloader/src/logging.rs +++ b/astro_modloader/src/logging.rs @@ -1,13 +1,24 @@ use std::fs; use std::io::prelude::*; -use std::sync::OnceLock; +use std::sync::{Mutex, OnceLock}; use colored::*; use log::{Level, LevelFilter, Log, Metadata, Record, SetLoggerError}; #[derive(Debug)] struct SimpleLogger { - file: fs::File, + file: Mutex, +} + +impl SimpleLogger { + fn lock(&self, f: impl FnOnce(&mut fs::File) -> T) -> T { + let mut guard = match self.file.lock() { + Ok(guard) => guard, + Err(err) => err.into_inner(), + }; + + f(&mut guard) + } } impl Log for SimpleLogger { @@ -53,18 +64,20 @@ impl Log for SimpleLogger { Level::Trace => "TRACE", }; - writeln!( - &self.file, - "[{level:<5} {file_path}:{}] {}", - record.line().unwrap_or(0), - record.args() - ) + self.lock(|file| { + writeln!( + file, + "[{level:<5} {file_path}:{}] {}", + record.line().unwrap_or(0), + record.args() + ) + }) .unwrap(); } } fn flush(&self) { - (&self.file).flush().unwrap() + self.lock(|file| file.flush()).unwrap() } } @@ -72,12 +85,14 @@ fn get_logger() -> &'static SimpleLogger { static LOGGER: OnceLock = OnceLock::new(); LOGGER.get_or_init(|| SimpleLogger { // open file - file: fs::OpenOptions::new() - .write(true) - .create(true) - .truncate(true) - .open("modloader_log.txt") - .unwrap(), + file: Mutex::new( + fs::OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open("modloader_log.txt") + .unwrap(), + ), }) }