protocol: Fix case where download can fail for small files.

There is another case where downloads of small files could fail if the
library side (writer) fails.  In this case the library would send back
a cancellation, but it would be received after the daemon had finished
sending the whole file (because the file is small enough).  The daemon
would reenter the main loop and immediately get an unexpected cancel
message, causing the daemon to die.

This commit also makes test-cancellation-download-librarycancels.sh
more robust.  We use Monte-Carlo testing with a range of file sizes.
Small file sizes should trigger the error case.
This commit is contained in:
Richard W.M. Jones
2011-08-18 19:13:32 +01:00
parent 06019bc82e
commit e4cba8f2b1
2 changed files with 26 additions and 6 deletions

View File

@@ -101,6 +101,12 @@ main_loop (int _sock)
"guestfsd: main_loop: new request, len 0x%" PRIx32 "\n",
len);
/* Cancellation sent from the library and received after the
* previous request has finished processing. Just ignore it.
*/
if (len == GUESTFS_CANCEL_FLAG)
continue;
if (len > GUESTFS_MESSAGE_MAX) {
fprintf (stderr, "guestfsd: incoming message is too long (%u bytes)\n",
len);

View File

@@ -18,22 +18,36 @@
# Test download where the library cancels.
#
#
# Download big and small files to /dev/full. This should fail but not
# kill the appliance. We test various randomized file sizes because
# there are many potential race conditions -- for example the daemon
# may or may not send all of its data because the error condition is
# detected.
set -e
rm -f test.img
../fish/guestfish <<'EOF'
add ../images/test.iso
size=$(awk 'BEGIN{ srand(); print int(16*1024*rand()) }')
echo "$0: test size $size (bytes)"
../fish/guestfish <<EOF
# We want the file to be fully allocated.
alloc test.img 10M
run
mount-ro /dev/sda /
part-disk /dev/sda mbr
mkfs ext2 /dev/sda1
mount-options "" /dev/sda1 /
# Download a file to /dev/full.
-download /100krandom /dev/full
fallocate64 /file $size
# Download the file into /dev/full so it fails.
-download /file /dev/full
# The daemon should still be reachable after the failure.
ping-daemon
EOF
rm -f test.img