fix: close playback progress readers between polls
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user