From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrew Cooper Subject: [PATCH 07/27] libxl: cancellation: Handle SIGTERM in save/restore helper Date: Mon, 15 Jun 2015 14:44:20 +0100 Message-ID: <1434375880-30914-8-git-send-email-andrew.cooper3@citrix.com> References: <1434375880-30914-1-git-send-email-andrew.cooper3@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1434375880-30914-1-git-send-email-andrew.cooper3@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: Xen-devel Cc: Wei Liu , Yang Hongyang , Ian Jackson , Ian Campbell List-Id: xen-devel@lists.xenproject.org From: Ian Jackson During startup of the save/restore helper, set the disposition of SIGTERM appropriately. For restore, we can simply die immediately - there is no point trying to do any kind of cleanup on what is now going to be a trashed domain. For save, we want to arrange that libxc's cleanup code (eg turning off logdirty) takes place. So our signal handler replaces the fd with one on which writes will fail, causing libxc's own loop to fail next time it actually tries to do a write. Currently this has only a minor beneficial effect: we don't send the helper a SIGTERM ourselves, and if someone else contrives to send our helper a SIGTERM they have probably sent one to libxl too in which case things are going to be a bit messy anyway. But in the next patch libxl is going to use SIGTERM itself on ao cancellation. Signed-off-by: Ian Jackson CC: Ian Campbell CC: Ian Jackson CC: Wei Liu --- tools/libxl/libxl_save_helper.c | 57 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tools/libxl/libxl_save_helper.c b/tools/libxl/libxl_save_helper.c index 7514b2e..4b72f24 100644 --- a/tools/libxl/libxl_save_helper.c +++ b/tools/libxl/libxl_save_helper.c @@ -40,8 +40,10 @@ #include #include #include +#include #include "libxl.h" +#include "libxl_utils.h" #include "xenctrl.h" #include "xenguest.h" @@ -120,6 +122,57 @@ static void *xmalloc(size_t sz) 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 = { { 0 } }; + sigset_t spmask; + int r; + + unwriteable_fd = open("/dev/null",O_RDONLY); + if (unwriteable_fd < 0) fail(errno,"open /dev/null for reading"); + + 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) @@ -229,6 +282,8 @@ int main(int argc, char **argv) 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); @@ -254,6 +309,8 @@ int main(int argc, char **argv) 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, -- 1.7.10.4