Debian Patches

Status for reprepro/5.3.1-5

Patch Description Author Forwarded Bugs Origin Last update
0001-uncompress-wait-until-the-child-as-exited-to-close-t.patch uncompress: close the pipe after the child exits (LP: #2008508)
Since we sometimes interrupt the decompression mid-stream as we're only
looking for specific data, e.g. the control file in control.tar.zstd, it
can happen that the child process still has a backlog of data to write
out to the pipes before exiting. If we close its stdout pipe before
calling waitpid(), it's going to encounter an EPIPE rather than
gracefully exit.

The fix is to only close the pipe fd after waitpid() successfully exits.

However, that introduces a new theoretical issue: the child process could
be blocking while writing into its stdout if the pipe is full, thus
leading to a deadlock. To avoid this, we have to drain the pipe before
waiting. Technically this should probably be done in a loop, but since
it's fairly unlikely to be blocked on stdout in the first place, having
enough pending data to fill the pipe *twice* seems too rare to bother
with in the first place.

The initial problem has first been noticed in Ubuntu autopkgtests on
s390x when upgrading to libarchive 3.6.2, where unzstd would loudly
complain about an -EPIPE (Ubuntu is using zstd as its default
compression algorithm). After investigation, it could be consistently
reproduced on low-powered s390x VMs with older libarchive releases,
where only the initial invocation would succeed, but subsequent attempts
would fail, presumably due performance changes via caching?

To reproduce the issue more reliably, I used the following Rust code to
produce a "proxy" unzstd that I dropped in /usr/local/bin. The output is
the same, but only written 1kB at a time with 500ms pauses.

```rust
use std::io::{Read, Write};
use std::process::{Command, Stdio};

fn main() {
let mut child = Command::new("zstd")
.arg("-d")
.stdin(Stdio::inherit())
.stdout(Stdio::piped())
.spawn()
.expect("Failed to spawn the command");
let mut stdout = child.stdout.take().unwrap();
let mut buffer = [0u8; 1024];
loop {
std::thread::sleep(std::time::Duration::from_millis(500));
let size = stdout.read(&mut buffer).unwrap();
if size > 0 {
std::io::stdout().write_all(&buffer[0..size]).unwrap();
std::io::stdout().flush().unwrap();
continue;
}
if let Some(status) = child.try_wait().unwrap() {
std::process::exit(status.code().unwrap())
}
}
}
```

(to compile it: `rustc unzstd.rs`)

Due to the Debian freeze, we'll probably ship this patch in Ubuntu as a
delta.
Simon Chopin <schopin@ubuntu.com> no upstream, 6a8ac062c49093ad33689754558e626851070e61 2023-03-01
0002-uncompress-prevent-reprepro-from-hanging-on-unzstd.patch Wait for poll event Bastian Germann <bage@debian.org> no 2024-01-08

All known versions for source package 'reprepro'

Links