fix: make log_msg writes atomic

Each log_msg opened the file in O_APPEND mode then used writeln!, which
issues a separate write() syscall per formatting fragment. O_APPEND only
guarantees atomicity per write() call, so concurrent log_msg calls from
the app's many threads/tasks could interleave their fragments mid-line.

Format the full line (timestamp + msg + newline) into one String, then
emit it with a single write_all so each log line lands as one atomic
append. No behavior change beyond non-interleaved output.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 15:43:08 -04:00
co-authored by Claude Opus 4.8
parent 821102beb6
commit e3b63c0856
+9 -5
View File
@@ -32,17 +32,21 @@ pub fn log_file_path() -> PathBuf {
}
pub fn log_msg(msg: &str) {
// Format the whole line into one buffer first, then emit it with a single
// `write_all`. The file is opened with `O_APPEND`, so a lone `write()` is
// atomic w.r.t. concurrent writers; building the line up front avoids the
// multi-syscall `writeln!` path that would let threads interleave fragments.
let line = match std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH) {
Ok(time) => format!("[{}.{:03}] {}\n", time.as_secs(), time.subsec_millis(), msg),
Err(_) => format!("{}\n", msg),
};
if let Ok(mut file) = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(log_path())
{
use std::io::Write;
if let Ok(time) = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH) {
let _ = writeln!(file, "[{}.{:03}] {}", time.as_secs(), time.subsec_millis(), msg);
} else {
let _ = writeln!(file, "{}", msg);
}
let _ = file.write_all(line.as_bytes());
}
}