#include <unistd.h>
#include <assert.h>
#include <inttypes.h>
+#include <fcntl.h>
#include "libxl.h"
+#include "libxl_utils.h"
#include "xenctrl.h"
#include "xenguest.h"
return r;
}
+/*----- signal handling -----*/
+
+static int unwriteable_fd;
+
+static void save_signal_handler(int num)
+{
+ /*
+ * We want to be able to interrupt save. But the code in libxc
+ * which does the actual saving is straight-through, and we need
+ * to execute its error path to put the guest back to sanity.
+ *
+ * So what we do is this: when we get the signal, we dup2
+ * the result of open("/dev/null",O_RDONLY) onto the output fd.
+ *
+ * This is guaranteed to 1. interrupt libxc's write (causing it to
+ * return short, or maybe EINTR); 2. make the next write give
+ * EBADF, so that: 3. at latest, libxc will notice when it next
+ * tries to write data and will then go into its cleanup path.
+ *
+ * We make no effort here to sanitise the resulting errors.
+ * That's libxl's job.
+ */
+ int esave = errno;
+
+ int r = dup2(unwriteable_fd, io_fd);
+ assert(r == io_fd); /* if not we can't write an xtl message because we
+ * might end up interleaving on our control stream */
+
+ errno = esave;
+}
+
+static void setup_signals(void (*handler)(int))
+{
+ struct sigaction sa;
+ sigset_t spmask;
+ int r;
+
+ unwriteable_fd = open("/dev/null",O_RDONLY);
+ if (unwriteable_fd < 0) fail(errno,"open /dev/null for reading");
+
+ LIBXL_FILLZERO(sa);
+ sa.sa_handler = handler;
+ sigemptyset(&sa.sa_mask);
+ r = sigaction(SIGTERM, &sa, 0);
+ if (r) fail(errno,"sigaction SIGTERM failed");
+
+ sigemptyset(&spmask);
+ sigaddset(&spmask,SIGTERM);
+ r = sigprocmask(SIG_UNBLOCK,&spmask,0);
+ if (r) fail(errno,"sigprocmask unblock SIGTERM failed");
+}
+
/*----- helper functions called by autogenerated stubs -----*/
unsigned char * helper_allocbuf(int len, void *user)
helper_setcallbacks_save(&helper_save_callbacks, cbflags);
startup("save");
+ setup_signals(save_signal_handler);
+
r = xc_domain_save(xch, io_fd, dom, max_iters, max_factor, flags,
&helper_save_callbacks, hvm);
complete(r);
unsigned long console_mfn = 0;
startup("restore");
+ setup_signals(SIG_DFL);
+
r = xc_domain_restore(xch, io_fd, dom, store_evtchn, &store_mfn,
store_domid, console_evtchn, &console_mfn,
console_domid, hvm, pae, superpages,