fix: leaky demuxer file handles

This commit is contained in:
kieran 2025-01-27 22:50:43 +00:00
parent 128f204253
commit a63b88ef3c
No known key found for this signature in database
GPG Key ID: DE71CEB3925BE941
3 changed files with 37 additions and 8 deletions

12
Cargo.lock generated
View File

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "aho-corasick"
@ -181,6 +181,7 @@ dependencies = [
"ffmpeg-sys-the-third",
"libc",
"log",
"rlimit",
"slimbox",
]
@ -333,6 +334,15 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rlimit"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7043b63bd0cd1aaa628e476b80e6d4023a3b50eb32789f2728908107bd0c793a"
dependencies = [
"libc",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"

View File

@ -17,3 +17,4 @@ log = "0.4.22"
[dev-dependencies]
env_logger = "0.11.5"
rlimit = "0.10.2"

View File

@ -250,14 +250,15 @@ impl Drop for Demuxer {
fn drop(&mut self) {
unsafe {
if !self.ctx.is_null() {
if let DemuxerInput::Reader(_, _) = self.input {
av_free((*(*self.ctx).pb).buffer as *mut _);
drop(SlimBox::<dyn Read>::from_raw((*(*self.ctx).pb).opaque));
match self.input {
DemuxerInput::Reader(_, _) => {
av_free((*(*self.ctx).pb).buffer as *mut _);
drop(SlimBox::<dyn Read>::from_raw((*(*self.ctx).pb).opaque));
avio_context_free(&mut (*self.ctx).pb);
}
_ => {}
}
if !(*self.ctx).pb.is_null() {
avio_context_free(&mut (*self.ctx).pb);
}
avformat_free_context(self.ctx);
avformat_close_input(&mut self.ctx);
}
}
}
@ -284,4 +285,21 @@ mod tests {
}
Ok(())
}
/// Test for leaking file handles
#[test]
fn probe_lots() -> Result<()> {
rlimit::setrlimit(rlimit::Resource::NOFILE, 64, 128)?;
let nof_limit = rlimit::Resource::NOFILE.get_hard()?;
for n in 0..nof_limit {
let mut demux = Demuxer::new("./test_output/test.png")?;
unsafe {
if let Err(e) = demux.probe_input() {
bail!("Failed on {}: {}", n, e);
}
}
}
Ok(())
}
}