[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Execute xc_linux_restore in a seperate process so that it can't



ChangeSet 1.1513.1.1, 2005/05/23 23:34:18+01:00, cl349@xxxxxxxxxxxxxxxxxxxx

        Execute xc_linux_restore in a seperate process so that it can't
        crash xend.  Also handle errors passed from xc_linux_restore and
        log info messages from xc_linux_restore.
        XendDomain.py:
          Popen xc_restore instead of calling xc_linux_restore directly.
        xc.c:
          Add pyxc_handle exporting the file descriptor to the control 
interface.
          Remove xc_linux_restore -- replaced by popen of xc_restore directly
          from python.
        xc_linux_restore.c:
          Enable debug output.
        xpopen.py:
          Add xpopen functionality:
          Optionally exclude a list of file descriptors from being closed, 
allowing
          access to those file descriptors from the command.
          Remove unused parts.
        xpopen.py, Makefile, xc_restore.c:
          new file
        Makefile:
          Add xcutils subdir.
        ignore:
          Add tools/xcutils/xc_restore.
        Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>



 Makefile                      |    1 
 libxc/xc_linux_restore.c      |    4 -
 python/xen/lowlevel/xc/xc.c   |   50 ++++--------------
 python/xen/util/xpopen.py     |  112 ++++++++++++++++++++++++++++++++++++++++++
 python/xen/xend/XendDomain.py |   29 ++++++++++
 xcutils/Makefile              |   62 +++++++++++++++++++++++
 xcutils/xc_restore.c          |   30 +++++++++++
 7 files changed, 247 insertions(+), 41 deletions(-)


diff -Nru a/tools/Makefile b/tools/Makefile
--- a/tools/Makefile    2005-05-23 20:02:59 -04:00
+++ b/tools/Makefile    2005-05-23 20:02:59 -04:00
@@ -10,6 +10,7 @@
 SUBDIRS += python
 SUBDIRS += xfrd
 SUBDIRS += xcs
+SUBDIRS += xcutils
 SUBDIRS += pygrub
 
 .PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
diff -Nru a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c
--- a/tools/libxc/xc_linux_restore.c    2005-05-23 20:02:59 -04:00
+++ b/tools/libxc/xc_linux_restore.c    2005-05-23 20:02:59 -04:00
@@ -11,7 +11,7 @@
 
 #define MAX_BATCH_SIZE 1024
 
-#define DEBUG 0
+#define DEBUG 01
 
 #if 1
 #define ERR(_f, _a...) fprintf ( stderr, _f , ## _a )
@@ -20,7 +20,7 @@
 #endif
 
 #if DEBUG
-#define DPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a )
+#define DPRINTF(_f, _a...) fprintf ( stdout, _f , ## _a )
 #else
 #define DPRINTF(_f, _a...) ((void)0)
 #endif
diff -Nru a/tools/python/xen/lowlevel/xc/xc.c 
b/tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c 2005-05-23 20:02:59 -04:00
+++ b/tools/python/xen/lowlevel/xc/xc.c 2005-05-23 20:02:59 -04:00
@@ -63,6 +63,13 @@
     return NULL;
 }
 
+static PyObject *pyxc_handle(PyObject *self)
+{
+    XcObject *xc = (XcObject *)self;
+
+    return PyInt_FromLong(xc->xc_handle);
+}
+
 static PyObject *pyxc_domain_create(PyObject *self,
                                     PyObject *args,
                                     PyObject *kwds)
@@ -334,36 +341,6 @@
     return val;
 }
 
-static PyObject *pyxc_linux_restore(PyObject *self,
-                                    PyObject *args,
-                                    PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    PyObject *val = NULL;
-    int rc =-1;
-    int io_fd, dom;
-    unsigned long nr_pfns;
-
-    static char *kwd_list[] = { "fd", "dom", "pfns", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iil", kwd_list,
-                                      &io_fd, &dom, &nr_pfns) )
-        goto exit;
-
-    rc = xc_linux_restore(xc->xc_handle, io_fd, dom, nr_pfns);
-    if ( rc != 0 )
-    {
-        PyErr_SetFromErrno(xc_error);
-        goto exit;
-    }
-
-    Py_INCREF(zero);
-    val = zero;
-
-  exit:
-    return val;
-}
-
 static PyObject *pyxc_linux_build(PyObject *self,
                                   PyObject *args,
                                   PyObject *kwds)
@@ -938,6 +915,11 @@
 
 
 static PyMethodDef pyxc_methods[] = {
+    { "handle",
+      (PyCFunction)pyxc_handle,
+      0, "\n"
+      "Query the xc control interface file descriptor.\n\n"
+      "Returns: [int] file descriptor\n" },
     { "domain_create", 
       (PyCFunction)pyxc_domain_create, 
       METH_VARARGS | METH_KEYWORDS, "\n"
@@ -1025,14 +1007,6 @@
       " state_file [str]:    Name of state file. Must not currently exist.\n"
       " progress   [int, 1]: Bool - display a running progress indication?\n\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "linux_restore", 
-      (PyCFunction)pyxc_linux_restore, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Restore the CPU and memory state of a Linux guest OS.\n"
-      " dom        [int]:    Identifier of domain to be restored.\n"
-      " pfns       [int]:    Number of pages domain uses.\n"
-      "Returns: [int] new domain identifier on success; -1 on error.\n" },
 
     { "linux_build", 
       (PyCFunction)pyxc_linux_build, 
diff -Nru a/tools/python/xen/util/xpopen.py b/tools/python/xen/util/xpopen.py
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/python/xen/util/xpopen.py   2005-05-23 20:02:59 -04:00
@@ -0,0 +1,112 @@
+"""Spawn a command with pipes to its stdin, stdout, and optionally stderr.
+
+The normal os.popen(cmd, mode) call spawns a shell command and provides a
+file interface to just the input or output of the process depending on
+whether mode is 'r' or 'w'.  This module provides the functions xpopen2(cmd)
+and xpopen3(cmd) which return two or three pipes to the spawned command.
+Optionally exclude a list of file descriptors from being closed, allowing
+access to those file descriptors from the command.
+"""
+
+import os
+import sys
+
+try:
+    MAXFD = os.sysconf('SC_OPEN_MAX')
+except (AttributeError, ValueError):
+    MAXFD = 256
+
+_active = []
+
+def _cleanup():
+    for inst in _active[:]:
+        inst.poll()
+
+class xPopen3:
+    """Class representing a child process.  Normally instances are created
+    by the factory functions popen2() and popen3()."""
+
+    sts = -1                    # Child not completed yet
+
+    def __init__(self, cmd, capturestderr=False, bufsize=-1, passfd=()):
+        """The parameter 'cmd' is the shell command to execute in a
+        sub-process.  The 'capturestderr' flag, if true, specifies that
+        the object should capture standard error output of the child process.
+        The default is false.  If the 'bufsize' parameter is specified, it
+        specifies the size of the I/O buffers to/from the child process."""
+        _cleanup()
+        self.passfd = passfd
+        p2cread, p2cwrite = os.pipe()
+        c2pread, c2pwrite = os.pipe()
+        if capturestderr:
+            errout, errin = os.pipe()
+        self.pid = os.fork()
+        if self.pid == 0:
+            # Child
+            os.dup2(p2cread, 0)
+            os.dup2(c2pwrite, 1)
+            if capturestderr:
+                os.dup2(errin, 2)
+            self._run_child(cmd)
+        os.close(p2cread)
+        self.tochild = os.fdopen(p2cwrite, 'w', bufsize)
+        os.close(c2pwrite)
+        self.fromchild = os.fdopen(c2pread, 'r', bufsize)
+        if capturestderr:
+            os.close(errin)
+            self.childerr = os.fdopen(errout, 'r', bufsize)
+        else:
+            self.childerr = None
+        _active.append(self)
+
+    def _run_child(self, cmd):
+        if isinstance(cmd, basestring):
+            cmd = ['/bin/sh', '-c', cmd]
+        for i in range(3, MAXFD):
+            if i in self.passfd:
+                continue
+            try:
+                os.close(i)
+            except OSError:
+                pass
+        try:
+            os.execvp(cmd[0], cmd)
+        finally:
+            os._exit(1)
+
+    def poll(self):
+        """Return the exit status of the child process if it has finished,
+        or -1 if it hasn't finished yet."""
+        if self.sts < 0:
+            try:
+                pid, sts = os.waitpid(self.pid, os.WNOHANG)
+                if pid == self.pid:
+                    self.sts = sts
+                    _active.remove(self)
+            except os.error:
+                pass
+        return self.sts
+
+    def wait(self):
+        """Wait for and return the exit status of the child process."""
+        if self.sts < 0:
+            pid, sts = os.waitpid(self.pid, 0)
+            if pid == self.pid:
+                self.sts = sts
+                _active.remove(self)
+        return self.sts
+
+
+def xpopen2(cmd, bufsize=-1, mode='t', passfd=[]):
+    """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
+    specified, it sets the buffer size for the I/O pipes.  The file objects
+    (child_stdout, child_stdin) are returned."""
+    inst = xPopen3(cmd, False, bufsize, passfd)
+    return inst.fromchild, inst.tochild
+
+def xpopen3(cmd, bufsize=-1, mode='t', passfd=[]):
+    """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
+    specified, it sets the buffer size for the I/O pipes.  The file objects
+    (child_stdout, child_stdin, child_stderr) are returned."""
+    inst = xPopen3(cmd, True, bufsize, passfd)
+    return inst.fromchild, inst.tochild, inst.childerr
diff -Nru a/tools/python/xen/xend/XendDomain.py 
b/tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py       2005-05-23 20:02:59 -04:00
+++ b/tools/python/xen/xend/XendDomain.py       2005-05-23 20:02:59 -04:00
@@ -25,7 +25,11 @@
 
 
 import errno
+import os
+import select
+from string import join
 from struct import pack, unpack, calcsize
+from xen.util.xpopen import xPopen3
 
 __all__ = [ "XendDomain" ]
 
@@ -325,6 +329,7 @@
         sizeof_int = calcsize("i")
         sizeof_unsigned_long = calcsize("L")
         PAGE_SIZE = 4096
+        PATH_XC_RESTORE = "/usr/libexec/xen/xc_restore"
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.