summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2011-08-18 19:13:32 +0100
committerRichard W.M. Jones <rjones@redhat.com>2011-08-18 20:02:30 +0100
commite4cba8f2b1a68e7361ce342ff659cccb0490446e (patch)
tree636ff61679b6d8c9c853857f80c2967f4de7d904
parent06019bc82e107f7715ebc59e491610e06dad1e39 (diff)
downloadlibguestfs-e4cba8f2b1a68e7361ce342ff659cccb0490446e.tar.gz
libguestfs-e4cba8f2b1a68e7361ce342ff659cccb0490446e.tar.xz
libguestfs-e4cba8f2b1a68e7361ce342ff659cccb0490446e.zip
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.
-rw-r--r--daemon/proto.c6
-rwxr-xr-xregressions/test-cancellation-download-librarycancels.sh26
2 files changed, 26 insertions, 6 deletions
diff --git a/daemon/proto.c b/daemon/proto.c
index 88e2d28c..238ee88c 100644
--- a/daemon/proto.c
+++ b/daemon/proto.c
@@ -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);
diff --git a/regressions/test-cancellation-download-librarycancels.sh b/regressions/test-cancellation-download-librarycancels.sh
index 20f89d23..5f6ebf1e 100755
--- a/regressions/test-cancellation-download-librarycancels.sh
+++ b/regressions/test-cancellation-download-librarycancels.sh
@@ -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