On 8/31/23 10:50, Richard W.M. Jones wrote: > See comment for explanation and > https://listman.redhat.com/archives/libguestfs/2023-August/032468.html > --- > tests/Makefile.am | 2 + > plugins/sh/call.c | 33 +++++++----- > tests/test-sh-pwrite-ignore-stdin.sh | 77 ++++++++++++++++++++++++++++ > 3 files changed, 100 insertions(+), 12 deletions(-) > > diff --git a/tests/Makefile.am b/tests/Makefile.am > index d57eb01b8..e69893e0d 100644 > --- a/tests/Makefile.am > +++ b/tests/Makefile.am > @@ -1325,11 +1325,13 @@ test-shell.img: > TESTS += \ > test-sh-errors.sh \ > test-sh-extents.sh \ > + test-sh-pwrite-ignore-stdin.sh \ > test-sh-tmpdir-leak.sh \ > $(NULL) > EXTRA_DIST += \ > test-sh-errors.sh \ > test-sh-extents.sh \ > + test-sh-pwrite-ignore-stdin.sh \ > test-sh-tmpdir-leak.sh \ > $(NULL) > > diff --git a/plugins/sh/call.c b/plugins/sh/call.c > index 888c6459a..621465252 100644 > --- a/plugins/sh/call.c > +++ b/plugins/sh/call.c > @@ -275,22 +275,31 @@ call3 (const char *wbuf, size_t wbuflen, /* sent to > stdin (can be NULL) */ > r = write (pfds[0].fd, wbuf, wbuflen); > if (r == -1) { > if (errno == EPIPE) { > - /* We tried to write to the script but it didn't consume > - * the data. Probably the script exited without reading > - * from stdin. This is an error in the script. > + /* In nbdkit <= 1.35.11 we gave an error here, arguing that > + * scripts must always consume or discard their full input > + * when 'pwrite' is called. Previously we had many cases > + * where scripts forgot to discard the data on a path out of > + * pwrite (such as an error or where the script is not > + * interested in the data being written), resulting in > + * intermittent test failures. > + * > + * It is valid for a script to ignore the written data > + * (plenty of non-sh plugins do this), or for a script to be > + * gradually processing the data, encounter an error and > + * wish to exit immediately. Therefore ignore this error. > */
I'm not reviewing the code changes in detail, just asking for a comment extension here: Can you highlight that, "if a script fails to consume all input due to a crash, we're going to catch that with waitpid() / WIFSIGNALED() below"? Basically I'd like us to show that we *know* that we cover for the case when an EPIPE might not be a conscious decision from the child script. ... Hmmm, let me check something: #!/bin/bash ulimit -f 1 cat >f $ ./script </dev/zero ./script: line 3: 18032 File size limit exceeded(core dumped) cat > f $ echo $? 153 $ kill -l 153 XFSZ Good! (This example simulates a subprocess of the pwrite script crashing with SIGXFSZ, due to exceeding the permitted file size limit, *and* the shell propagating that crashing exit status up to nbdkit's sh plugin.) Acked-by: Laszlo Ersek <ler...@redhat.com> Laszlo > - nbdkit_error ("%s: write to script failed because of a broken > pipe: " > - "this can happen if the script exits without " > - "consuming stdin, which usually indicates a bug " > - "in the script", > - argv0); > + nbdkit_debug ("%s: write: %m (ignored)", argv0); > + wbuflen = 0; /* discard the rest */ > } > - else > + else { > nbdkit_error ("%s: write: %m", argv0); > - goto error; > + goto error; > + } > + } > + else { > + wbuf += r; > + wbuflen -= r; > } > - wbuf += r; > - wbuflen -= r; > /* After writing all the data we close the pipe so that > * the reader on the other end doesn't wait for more. > */ > diff --git a/tests/test-sh-pwrite-ignore-stdin.sh > b/tests/test-sh-pwrite-ignore-stdin.sh > new file mode 100755 > index 000000000..3448eca17 > --- /dev/null > +++ b/tests/test-sh-pwrite-ignore-stdin.sh > @@ -0,0 +1,77 @@ > +#!/usr/bin/env bash > +# nbdkit > +# Copyright Red Hat > +# > +# Redistribution and use in source and binary forms, with or without > +# modification, are permitted provided that the following conditions are > +# met: > +# > +# * Redistributions of source code must retain the above copyright > +# notice, this list of conditions and the following disclaimer. > +# > +# * Redistributions in binary form must reproduce the above copyright > +# notice, this list of conditions and the following disclaimer in the > +# documentation and/or other materials provided with the distribution. > +# > +# * Neither the name of Red Hat nor the names of its contributors may be > +# used to endorse or promote products derived from this software without > +# specific prior written permission. > +# > +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND > +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, > +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A > +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR > +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF > +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND > +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, > +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT > +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > +# SUCH DAMAGE. > + > +# Test that pwrite is allowed to ignore stdin (in nbdkit >= 1.36). > + > +source ./functions.sh > +set -e > +set -x > + > +requires_plugin sh > +requires_nbdsh_uri > + > +sock=$(mktemp -u /tmp/nbdkit-test-sock.XXXXXX) > +pid=sh-pwrite-ignore-stdin.pid > +files="$sock $pid" > +rm -f $files > +cleanup_fn rm -f $files > + > +start_nbdkit -P $pid -U $sock sh - <<'EOF' > +case "$1" in > + can_write) echo 0 ;; > + pwrite) > + # Always ignore the input. If the offset >= 32M return an error. > + if [ $4 -ge 33554432 ]; then > + echo 'ENOSPC Out of space' >&2 > + exit 1 > + fi > + ;; > + get_size) > + echo 64M > + ;; > + pread) > + ;; > + *) exit 2 ;; > +esac > +EOF > + > +nbdsh -u "nbd+unix://?socket=$sock" -c ' > +buf = bytearray(16*1024*1024) > +h.pwrite(buf, 0) > + > +try: > + h.pwrite(buf, 32*1024*1024) > + assert False > +except nbd.Error: > + # Expect an error here. > + pass > +' _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://listman.redhat.com/mailman/listinfo/libguestfs