summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--daemon/base64.c5
-rw-r--r--daemon/debug.c5
-rw-r--r--daemon/tar.c5
-rw-r--r--daemon/upload.c5
-rw-r--r--generator/generator_c.ml2
-rw-r--r--generator/generator_daemon.ml10
-rw-r--r--regressions/Makefile.am2
-rw-r--r--src/guestfs-internal.h1
-rw-r--r--src/proto.c31
9 files changed, 53 insertions, 13 deletions
diff --git a/daemon/base64.c b/daemon/base64.c
index 7e07a6ad..f55e1f51 100644
--- a/daemon/base64.c
+++ b/daemon/base64.c
@@ -77,8 +77,11 @@ do_base64_in (const char *file)
return -1;
}
if (r == -2) { /* cancellation from library */
+ /* This error is ignored by the library since it initiated the
+ * cancel. Nevertheless we must send an error reply here.
+ */
+ reply_with_error ("file upload cancelled");
pclose (fp);
- /* Do NOT send any error. */
return -1;
}
diff --git a/daemon/debug.c b/daemon/debug.c
index 091e7410..cd3e8a5f 100644
--- a/daemon/debug.c
+++ b/daemon/debug.c
@@ -540,8 +540,11 @@ do_debug_upload (const char *filename, int mode)
return -1;
}
if (r == -2) { /* cancellation from library */
+ /* This error is ignored by the library since it initiated the
+ * cancel. Nevertheless we must send an error reply here.
+ */
+ reply_with_error ("file upload cancelled");
close (fd);
- /* Do NOT send any error. */
return -1;
}
diff --git a/daemon/tar.c b/daemon/tar.c
index 3c756afc..39fce8c9 100644
--- a/daemon/tar.c
+++ b/daemon/tar.c
@@ -118,8 +118,11 @@ do_tXz_in (const char *dir, const char *filter)
return -1;
}
if (r == -2) { /* cancellation from library */
+ /* This error is ignored by the library since it initiated the
+ * cancel. Nevertheless we must send an error reply here.
+ */
+ reply_with_error ("file upload cancelled");
pclose (fp);
- /* Do NOT send any error. */
return -1;
}
diff --git a/daemon/upload.c b/daemon/upload.c
index f8d312ff..2c429694 100644
--- a/daemon/upload.c
+++ b/daemon/upload.c
@@ -94,8 +94,11 @@ upload (const char *filename, int flags, int64_t offset)
return -1;
}
if (r == -2) { /* cancellation from library */
+ /* This error is ignored by the library since it initiated the
+ * cancel. Nevertheless we must send an error reply here.
+ */
+ reply_with_error ("file upload cancelled");
close (data.fd);
- /* Do NOT send any error. */
return -1;
}
diff --git a/generator/generator_c.ml b/generator/generator_c.ml
index aee2d774..648ff687 100644
--- a/generator/generator_c.ml
+++ b/generator/generator_c.ml
@@ -1177,6 +1177,8 @@ trace_send_line (guestfs_h *g)
pr " if (r == -1) {\n";
pr " guestfs___end_busy (g);\n";
trace_return_error ~indent:4 shortname style errcode;
+ pr " /* daemon will send an error reply which we discard */\n";
+ pr " guestfs___recv_discard (g, \"%s\");\n" shortname;
pr " return %s;\n" (string_of_errcode errcode);
pr " }\n";
pr " if (r == -2) /* daemon cancelled */\n";
diff --git a/generator/generator_daemon.ml b/generator/generator_daemon.ml
index 8c3a5486..f5c1fa3e 100644
--- a/generator/generator_daemon.ml
+++ b/generator/generator_daemon.ml
@@ -128,7 +128,7 @@ and generate_daemon_actions () =
let mask = Int64.lognot (Int64.pred (Int64.shift_left 1L len)) in
pr " if (optargs_bitmask & UINT64_C(0x%Lx)) {\n" mask;
if is_filein then
- pr " if (cancel_receive () != -2)\n";
+ pr " cancel_receive ();\n";
pr " reply_with_error (\"unknown option in optional arguments bitmask (this can happen if a program is compiled against a newer version of libguestfs, then run against an older version of the daemon)\");\n";
pr " goto done;\n";
pr " }\n";
@@ -141,8 +141,8 @@ and generate_daemon_actions () =
pr "\n";
pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
if is_filein then
- pr " if (cancel_receive () != -2)\n";
- pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
+ pr " cancel_receive ();\n";
+ pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
pr " goto done;\n";
pr " }\n";
let pr_args n =
@@ -153,8 +153,8 @@ and generate_daemon_actions () =
pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
pr " if (%s == NULL) {\n" n;
if is_filein then
- pr " if (cancel_receive () != -2)\n";
- pr " reply_with_perror (\"realloc\");\n";
+ pr " cancel_receive ();\n";
+ pr " reply_with_perror (\"realloc\");\n";
pr " goto done;\n";
pr " }\n";
pr " %s[args.%s.%s_len] = NULL;\n" n n n;
diff --git a/regressions/Makefile.am b/regressions/Makefile.am
index 6527e063..b01d3a5a 100644
--- a/regressions/Makefile.am
+++ b/regressions/Makefile.am
@@ -33,6 +33,7 @@ TESTS = \
rhbz578407.sh \
rhbz580246.sh \
test-add-domain.sh \
+ test-both-ends-cancel.sh \
test-cancellation-download-librarycancels.sh \
test-cancellation-upload-daemoncancels.sh \
test-copy.sh \
@@ -59,7 +60,6 @@ SKIPPED_TESTS = \
test-bootbootboot.sh
FAILING_TESTS = \
- test-both-ends-cancel.sh \
test-qemudie-launchfail.sh
random_val := $(shell awk 'BEGIN{srand(); print 1+int(255*rand())}' < /dev/null)
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 7223a884..ccc5bb5f 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -289,6 +289,7 @@ extern int guestfs___set_busy (guestfs_h *g);
extern int guestfs___end_busy (guestfs_h *g);
extern int guestfs___send (guestfs_h *g, int proc_nr, uint64_t progress_hint, uint64_t optargs_bitmask, xdrproc_t xdrp, char *args);
extern int guestfs___recv (guestfs_h *g, const char *fn, struct guestfs_message_header *hdr, struct guestfs_message_error *err, xdrproc_t xdrp, char *ret);
+extern int guestfs___recv_discard (guestfs_h *g, const char *fn);
extern int guestfs___send_file (guestfs_h *g, const char *filename);
extern int guestfs___recv_file (guestfs_h *g, const char *filename);
extern int guestfs___send_to_daemon (guestfs_h *g, const void *v_buf, size_t n);
diff --git a/src/proto.c b/src/proto.c
index 2ca24c29..cda731e5 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -848,9 +848,6 @@ guestfs___send_file (guestfs_h *g, const char *filename)
if (fd == -1) {
perrorf (g, "open: %s", filename);
send_file_cancellation (g);
- /* Daemon sees cancellation and won't reply, so caller can
- * just return here.
- */
return -1;
}
@@ -1034,6 +1031,34 @@ guestfs___recv (guestfs_h *g, const char *fn,
return 0;
}
+/* Same as guestfs___recv, but it discards the reply message. */
+int
+guestfs___recv_discard (guestfs_h *g, const char *fn)
+{
+ void *buf;
+ uint32_t size;
+ int r;
+
+ again:
+ r = guestfs___recv_from_daemon (g, &size, &buf);
+ if (r == -1)
+ return -1;
+
+ /* This can happen if a cancellation happens right at the end
+ * of us sending a FileIn parameter to the daemon. Discard. The
+ * daemon should send us an error message next.
+ */
+ if (size == GUESTFS_CANCEL_FLAG)
+ goto again;
+
+ if (size == GUESTFS_LAUNCH_FLAG) {
+ error (g, "%s: received unexpected launch flag from daemon when expecting reply", fn);
+ return -1;
+ }
+
+ return 0;
+}
+
/* Receive a file. */
/* Returns -1 = error, 0 = EOF, > 0 = more data */