Keep a strict read error over the empty-output MkvInvalid it causes

This commit is contained in:
Matthew Jackson
2026-10-01 15:23:31 -07:00
parent 134fdd973f
commit ca0f9d5bc8
3 changed files with 32 additions and 4 deletions
+30 -2
View File
@@ -1029,9 +1029,19 @@ impl Sink<PesFrame> for WriteSink {
Ok(Flow::Continue)
}
// After a read failure the read error is the title's failure: ending the output it
// cut short can fail (an mkv with no frames is `MkvInvalid`) but never replaces it.
fn close(self) -> Result<SinkClose, Error> {
let complete = !self.read_failed.load(Ordering::Relaxed);
self.end(complete)
if !self.read_failed.load(Ordering::Relaxed) {
return self.end(true);
}
self.end(false).or_else(|e| {
tracing::warn!(target: "mux", error = %e, "ending the output a read failure cut short failed");
Ok(SinkClose {
bytes: 0,
undelivered: Vec::new(),
})
})
}
// A stopped title is incomplete too: a wire sink must not end it cleanly.
@@ -1150,6 +1160,24 @@ mod tests {
assert!(log.is_empty(), "a failed sink is never finalised: {log:?}");
}
// A strict read failure before any frame lands: the mkv's zero-frame `MkvInvalid` on
// ending the output is a skippable stub code and must not replace the read error.
#[test]
fn a_read_failure_before_any_frame_is_not_a_skippable_stub() {
let dir = tempfile::tempdir().expect("tempdir");
let url = format!("mkv://{}", dir.path().join("o.mkv").display());
let mut fs = FakeStream::new(1).with_frames(10);
fs.fail_read_at = Some(0);
let ctx = crate::ctx::Ctx::new(Halt::new());
let err = drive_mux(Box::new(fs), &url, &ctx, None, None).expect_err("a read failure");
assert_eq!(
crate::error::error_code(&err),
Some(crate::error::E_DISC_READ),
"got {err}"
);
assert!(!crate::error::is_skippable_title_stub(&err));
}
// A stop ends the output incomplete; a clean drain finishes it.
#[test]
fn only_a_clean_drain_finishes_the_output() {
@@ -18,7 +18,7 @@ iso-null outcome = completed=true opened=true bytes=26416 errors=0 lost=0 stream
iso-mkv-raw refused = E6008
iso-mkv-selection outcome = completed=true opened=true bytes=20016 errors=0 lost=0 streams=2 undelivered=[]
iso-mkv-selection out o.mkv = 21563 bytes sha256:cda2cf35944d0511ffd8de92d4a542fd
live-mkv refused = E6008
live-mkv refused = E6000
live-mkv out o.mkv = 493 bytes sha256:454f3eb165010aa1646faed1279583cf
live-mkv-raw refused = E6000
live-mkv-skip outcome = completed=true opened=true bytes=17910 errors=7 lost=6144 streams=3 undelivered=[]
@@ -1,4 +1,4 @@
strict refused = E6008
strict refused = E6000
strict out o.mkv = 489 bytes sha256:8628b7bc94f1815e2948a4ce9f32c10f
skip outcome = completed=true opened=true bytes=17910 errors=7 lost=6144 streams=3 undelivered=[]
skip out o.mkv = 19705 bytes sha256:e8bf5f82342443c240a95385c881d3e2