fix: close playback progress readers between polls

This commit is contained in:
2026-10-26 15:29:17 +01:00
parent 65200626d2
commit 0a8a3451c4
3 changed files with 75 additions and 8 deletions
+64
View File
@@ -580,6 +580,70 @@ fn watched_write_failure_keeps_memory_unchanged_and_retries_consumed_reports() {
assert!(!state.poll_progress().unwrap());
}
#[cfg(unix)]
#[test]
fn historical_progress_sessions_leave_descriptors_available_for_subprocesses() {
const CHILD: &str = "TUBULAR_PROGRESS_DESCRIPTOR_TEST";
if std::env::var_os(CHILD).is_none() {
let output = std::process::Command::new(std::env::current_exe().unwrap())
.args([
"--exact",
"video_state::tests::historical_progress_sessions_leave_descriptors_available_for_subprocesses",
"--test-threads=1",
])
.env(CHILD, "1")
.output()
.unwrap();
assert!(
output.status.success(),
"{}\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
return;
}
// Isolate the process-wide limit from the rest of the test suite.
let mut limit = libc::rlimit {
rlim_cur: 0,
rlim_max: 0,
};
// SAFETY: limit is valid writable storage; only this child process is affected.
unsafe {
assert_eq!(libc::getrlimit(libc::RLIMIT_NOFILE, &mut limit), 0);
limit.rlim_cur = limit.rlim_cur.min(64);
assert_eq!(libc::setrlimit(libc::RLIMIT_NOFILE, &limit), 0);
}
let directory = TestDirectory::new();
let mut state = State::open(&directory.config()).unwrap();
let video = video();
let reports = state.progress_files(&vec![video.clone(); 96]).unwrap();
for report in &reports {
register_identity(report, &video.id).unwrap();
append(report, record(&video.id, "progress", false, 0.0).as_bytes());
}
let last = reports.last().unwrap();
let completion = record(&video.id, "closed", true, 95.0);
append(last, &completion.as_bytes()[..completion.len() - 1]);
drop(state);
let mut state = State::open(&directory.config()).unwrap();
for _ in 0..12 {
state.poll_progress().unwrap();
}
assert!(!state.is_watched(&video.id));
append(last, b"\n");
for _ in 0..6 {
state.poll_progress().unwrap();
}
assert!(state.is_watched(&video.id));
let output = std::process::Command::new("/usr/bin/true")
.output()
.expect("progress monitoring must leave descriptors available for subprocess pipes");
assert!(output.status.success());
}
#[test]
fn partial_reports_survive_restart_and_bad_siblings_do_not_block_completion() {
let directory = TestDirectory::new();