#3357: preserve concurrent session log identity

This commit is contained in:
FredApps
2026-11-09 22:04:08 +01:00
parent 47c9b4a99b
commit 8d9d9c446b
2 changed files with 47 additions and 4 deletions
+21 -1
View File
@@ -214,10 +214,16 @@ fn rotate(dir: &Path) -> std::io::Result<(PathBuf, File)> {
}
}
let path = numbered(dir, 0);
let file = File::create(&path)?;
let file = create_session_file(&path)?;
Ok((path, file))
}
// Another process may create the current log after our rotation. Never truncate its
// file: its writer and crash reporter may already hold the same inode open.
fn create_session_file(path: &Path) -> std::io::Result<File> {
std::fs::OpenOptions::new().write(true).create_new(true).open(path)
}
/// Rotate the session logs in `dir` (the `Logs` folder, see [`log_dir`]) and write records to
/// a fresh `effectcraft.log` there, first the ones logged so far; returns its path.
pub fn attach_session_log(dir: &Path) -> Result<PathBuf, String> {
@@ -428,6 +434,20 @@ mod tests {
assert_eq!(timestamp(u64::MAX), "584556019-04-03T14:25:51.615Z");
}
#[test]
fn concurrent_session_creation_does_not_truncate_the_winner() {
let dir = temp_dir("concurrent-create");
std::fs::create_dir_all(&dir).unwrap();
let path = dir.join(SESSION_LOG);
let mut winner = create_session_file(&path).unwrap();
winner.write_all(b"crash-report session 1-2\nwinner content\n").unwrap();
assert_eq!(create_session_file(&path).unwrap_err().kind(), std::io::ErrorKind::AlreadyExists);
winner.write_all(b"still the same session\n").unwrap();
assert_eq!(read(&path), "crash-report session 1-2\nwinner content\nstill the same session\n");
drop(winner);
std::fs::remove_dir_all(dir).unwrap();
}
/// Each launch keeps the previous runs' logs, so the log of a run that crashed survives.
#[test]
fn rotation_keeps_the_previous_logs_and_starts_an_empty_file() {