[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] Fix qemu spawn for Solaris
# HG changeset patch # User John Levon <john.levon@xxxxxxx> # Date 1236822270 25200 # Node ID 93d25b0df1be0abc503ff721e291b6a1553f4da2 # Parent 403118d22a30b83b863609ae4e0a7f694e612e42 Fix qemu spawn for Solaris On Solaris, xend runs in a 'process contract' such that all children are killed when the service is restarted. Spawn qemu processes in a new contract to avoid this. Signed-off-by: John Levon <john.levon@xxxxxxx> diff --git a/tools/python/setup.py b/tools/python/setup.py --- a/tools/python/setup.py +++ b/tools/python/setup.py @@ -38,6 +38,13 @@ scf = Extension("scf", libraries = libraries, sources = [ "xen/lowlevel/scf/scf.c" ]) +process = Extension("process", + extra_compile_args = extra_compile_args, + include_dirs = include_dirs + [ "xen/lowlevel/process" ], + library_dirs = library_dirs, + libraries = libraries + [ "contract" ], + sources = [ "xen/lowlevel/process/process.c" ]) + acm = Extension("acm", extra_compile_args = extra_compile_args, include_dirs = include_dirs + [ "xen/lowlevel/acm" ], @@ -63,6 +70,7 @@ modules = [ xc, xs, ptsname, acm, flask modules = [ xc, xs, ptsname, acm, flask ] if os.uname()[0] == 'SunOS': modules.append(scf) + modules.append(process) setup(name = 'xen', version = '3.0', diff --git a/tools/python/xen/lowlevel/process/process.c b/tools/python/xen/lowlevel/process/process.c new file mode 100644 --- /dev/null +++ b/tools/python/xen/lowlevel/process/process.c @@ -0,0 +1,164 @@ +/* + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <Python.h> + +#include <libcontract.h> +#include <sys/contract/process.h> +#include <fcntl.h> +#include <stdio.h> + +/* + * On Solaris, xend runs under a contract as an smf(5) service. As a + * result, when spawning long-running children such as a domain's + * qemu-dm instantiation, we have to make sure it's in a separate + * contract. Before we fork, we must activate a separate process + * contract template to place the child processes in a new contract. + */ + +static PyObject * +pyprocess_activate(PyObject *o, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "name", NULL }; + char *name = NULL; + int flags; + int cfd; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &name)) + return (NULL); + + cfd = open64("/system/contract/process/template", O_RDWR); + + if (cfd == -1) + goto err; + + if ((flags = fcntl(cfd, F_GETFD, 0)) == -1) + goto err; + + if (fcntl(cfd, F_SETFD, flags | FD_CLOEXEC) == -1) + goto err; + + if (name != NULL) + ct_pr_tmpl_set_svc_aux(cfd, name); + + if (ct_tmpl_activate(cfd)) + goto err; + + return (PyInt_FromLong((long)cfd)); + +err: + if (cfd != -1) + close(cfd); + PyErr_SetFromErrno(PyExc_OSError); + return (NULL); +} + +static PyObject * +pyprocess_clear(PyObject *o, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "contract", NULL }; + int cfd; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &cfd)) + return (NULL); + + if (ct_tmpl_clear(cfd) != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return (NULL); + } + + close(cfd); + + Py_INCREF(Py_None); + return (Py_None); +} + +static PyObject * +pyprocess_abandon_latest(PyObject *o, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { NULL }; + static char path[PATH_MAX]; + ct_stathdl_t st; + ctid_t latest; + int cfd; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist)) + return (NULL); + + cfd = open64("/system/contract/process/latest", O_RDONLY); + if (cfd == -1) + goto err; + + ct_status_read(cfd, CTD_COMMON, &st); + latest = ct_status_get_id(st); + ct_status_free(st); + close(cfd); + + snprintf(path, PATH_MAX, "/system/contract/process/%ld/ctl", + (long)latest); + + if ((cfd = open64(path, O_WRONLY)) < 0) + goto err; + if (ct_ctl_abandon(cfd)) + goto err; + close(cfd); + + Py_INCREF(Py_None); + return (Py_None); +err: + PyErr_SetFromErrno(PyExc_OSError); + return (NULL); +} + +PyDoc_STRVAR(pyprocess_activate__doc__, + "activate(name)\n" + "\n" + "Activate a new process contract template. If name is given,\n" + "it is used as the template's auxiliary value.\n" + "Returns the new contract template.\n"); + +PyDoc_STRVAR(pyprocess_clear__doc__, + "clear(contract)\n" + "\n" + "Clear and close the given contract template.\n"); + +PyDoc_STRVAR(pyprocess_abandon_latest__doc__, + "abandon_latest()\n" + "\n" + "Abandon the latest contract created by this thread.\n"); + +static struct PyMethodDef pyprocess_module_methods[] = { + { "activate", (PyCFunction) pyprocess_activate, + METH_VARARGS|METH_KEYWORDS, pyprocess_activate__doc__ }, + { "clear", (PyCFunction) pyprocess_clear, + METH_VARARGS|METH_KEYWORDS, pyprocess_clear__doc__ }, + { "abandon_latest", (PyCFunction) pyprocess_abandon_latest, + METH_VARARGS|METH_KEYWORDS, pyprocess_abandon_latest__doc__ }, + { NULL, NULL, 0, NULL } +}; + +PyMODINIT_FUNC +initprocess(void) +{ + Py_InitModule("process", pyprocess_module_methods); +} diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -40,6 +40,7 @@ from xen.xend import XendOptions from xen.xend import XendOptions from xen.util import oshelp from xen.util import utils +from xen.xend import osdep xc = xen.lowlevel.xc.xc() @@ -407,9 +408,12 @@ class ImageHandler: logfd = os.open(self.logfile, logfile_mode) sys.stderr.flush() + contract = osdep.prefork("%s:%d" % + (self.vm.getName(), self.vm.getDomid())) pid = os.fork() if pid == 0: #child try: + osdep.postfork(contract) os.dup2(null, 0) os.dup2(logfd, 1) os.dup2(logfd, 2) @@ -426,6 +430,7 @@ class ImageHandler: except: os._exit(127) else: + osdep.postfork(contract, abandon=True) self.pid = pid os.close(null) os.close(logfd) diff --git a/tools/python/xen/xend/osdep.py b/tools/python/xen/xend/osdep.py --- a/tools/python/xen/xend/osdep.py +++ b/tools/python/xen/xend/osdep.py @@ -290,6 +290,32 @@ _boot_dev = { "SunOS": _solaris_boot_dev } +def _default_prefork(name): + pass + +def _default_postfork(ct, abandon=False): + pass + +# call this for long-running processes that should survive a xend +# restart +def _solaris_prefork(name): + from xen.lowlevel import process + return process.activate(name) + +def _solaris_postfork(ct, abandon=False): + from xen.lowlevel import process + process.clear(ct) + if abandon: + process.abandon_latest() + +_get_prefork = { + "SunOS": _solaris_prefork +} + +_get_postfork = { + "SunOS": _solaris_postfork +} + def _get(var, default=None): return var.get(os.uname()[0], default) @@ -304,3 +330,5 @@ connection_allowed = _get(_connection_al connection_allowed = _get(_connection_allowed, _default_connection_allowed) get_boot_dev = _get(_boot_dev, _default_boot_dev) do_broadcast = _get(_do_broadcast) +prefork = _get(_get_prefork, _default_prefork) +postfork = _get(_get_postfork, _default_postfork) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |