If .prepare fails, we do not want to call .finalize (similar to how if .open fails, we do not want to call .close). However, the logic in backend_finalize was checking on the wrong condition ('was the connection opened' rather than 'was the connection prepared'), which led to an assertion failure. Simple reproducer: $ nbdkit -U - -f --filter cache --run 'qemu-io -r -c quit $nbd' sh - <<\EOF
case $1 in get_size) echo oops >&2; exit 1 ;; *) exit 2 ;; esac EOF nbdkit: sh[1]: error: /tmp/nbdkitshYvAQbz/inline-script.sh: oops nbdkit: backend.c:206: backend_finalize: Assertion `h->state & HANDLE_CONNECTED' failed. qemu-io: can't open device nbd:unix:/tmp/nbdkit60FUTw/socket: Failed to read option reply: Unexpected end-of-file before all bytes were read nbdkit: nbdkit command was killed by signal 6
With this patch, the command now fails gracefully: nbdkit: sh[1]: error: /tmp/nbdkitshie18Lp/inline-script.sh: oops qemu-io: can't open device nbd:unix:/tmp/nbdkitqvAOlr/socket: Requested export not available Fixes: ffa98c8d Signed-off-by: Eric Blake <eblake@redhat.com> --- Pushing this to master and stable-1.16 server/backend.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/server/backend.c b/server/backend.c index 8bfa8525..753f5cca 100644 --- a/server/backend.c +++ b/server/backend.c @@ -221,15 +221,13 @@ backend_finalize (struct backend *b) if (h->state & HANDLE_FAILED) return -1; - if (h->handle) { - assert (h->state & HANDLE_CONNECTED); + assert (h->state & HANDLE_OPEN); + if (h->state & HANDLE_CONNECTED) { if (b->finalize (b, h->handle) == -1) { h->state |= HANDLE_FAILED; return -1; } } - else - assert (! (h->state & HANDLE_CONNECTED)); if (b->i) return backend_finalize (b->next); -- 2.24.1