ia64/xen-unstable

view tools/python/xen/lowlevel/process/process.c @ 19333:e2de0e760a0d

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@sun.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Mar 12 11:07:00 2009 +0000 (2009-03-12)
parents
children
line source
1 /*
2 * Permission is hereby granted, free of charge, to any person obtaining a copy
3 * of this software and associated documentation files (the "Software"), to
4 * deal in the Software without restriction, including without limitation the
5 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6 * sell copies of the Software, and to permit persons to whom the Software is
7 * furnished to do so, subject to the following conditions:
8 *
9 * The above copyright notice and this permission notice shall be included in
10 * all copies or substantial portions of the Software.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18 * DEALINGS IN THE SOFTWARE.
19 *
20 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
21 * Use is subject to license terms.
22 */
24 #include <Python.h>
26 #include <libcontract.h>
27 #include <sys/contract/process.h>
28 #include <fcntl.h>
29 #include <stdio.h>
31 /*
32 * On Solaris, xend runs under a contract as an smf(5) service. As a
33 * result, when spawning long-running children such as a domain's
34 * qemu-dm instantiation, we have to make sure it's in a separate
35 * contract. Before we fork, we must activate a separate process
36 * contract template to place the child processes in a new contract.
37 */
39 static PyObject *
40 pyprocess_activate(PyObject *o, PyObject *args, PyObject *kwargs)
41 {
42 static char *kwlist[] = { "name", NULL };
43 char *name = NULL;
44 int flags;
45 int cfd;
47 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &name))
48 return (NULL);
50 cfd = open64("/system/contract/process/template", O_RDWR);
52 if (cfd == -1)
53 goto err;
55 if ((flags = fcntl(cfd, F_GETFD, 0)) == -1)
56 goto err;
58 if (fcntl(cfd, F_SETFD, flags | FD_CLOEXEC) == -1)
59 goto err;
61 if (name != NULL)
62 ct_pr_tmpl_set_svc_aux(cfd, name);
64 if (ct_tmpl_activate(cfd))
65 goto err;
67 return (PyInt_FromLong((long)cfd));
69 err:
70 if (cfd != -1)
71 close(cfd);
72 PyErr_SetFromErrno(PyExc_OSError);
73 return (NULL);
74 }
76 static PyObject *
77 pyprocess_clear(PyObject *o, PyObject *args, PyObject *kwargs)
78 {
79 static char *kwlist[] = { "contract", NULL };
80 int cfd;
82 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &cfd))
83 return (NULL);
85 if (ct_tmpl_clear(cfd) != 0) {
86 PyErr_SetFromErrno(PyExc_OSError);
87 return (NULL);
88 }
90 close(cfd);
92 Py_INCREF(Py_None);
93 return (Py_None);
94 }
96 static PyObject *
97 pyprocess_abandon_latest(PyObject *o, PyObject *args, PyObject *kwargs)
98 {
99 static char *kwlist[] = { NULL };
100 static char path[PATH_MAX];
101 ct_stathdl_t st;
102 ctid_t latest;
103 int cfd;
105 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
106 return (NULL);
108 cfd = open64("/system/contract/process/latest", O_RDONLY);
109 if (cfd == -1)
110 goto err;
112 ct_status_read(cfd, CTD_COMMON, &st);
113 latest = ct_status_get_id(st);
114 ct_status_free(st);
115 close(cfd);
117 snprintf(path, PATH_MAX, "/system/contract/process/%ld/ctl",
118 (long)latest);
120 if ((cfd = open64(path, O_WRONLY)) < 0)
121 goto err;
122 if (ct_ctl_abandon(cfd))
123 goto err;
124 close(cfd);
126 Py_INCREF(Py_None);
127 return (Py_None);
128 err:
129 PyErr_SetFromErrno(PyExc_OSError);
130 return (NULL);
131 }
133 PyDoc_STRVAR(pyprocess_activate__doc__,
134 "activate(name)\n"
135 "\n"
136 "Activate a new process contract template. If name is given,\n"
137 "it is used as the template's auxiliary value.\n"
138 "Returns the new contract template.\n");
140 PyDoc_STRVAR(pyprocess_clear__doc__,
141 "clear(contract)\n"
142 "\n"
143 "Clear and close the given contract template.\n");
145 PyDoc_STRVAR(pyprocess_abandon_latest__doc__,
146 "abandon_latest()\n"
147 "\n"
148 "Abandon the latest contract created by this thread.\n");
150 static struct PyMethodDef pyprocess_module_methods[] = {
151 { "activate", (PyCFunction) pyprocess_activate,
152 METH_VARARGS|METH_KEYWORDS, pyprocess_activate__doc__ },
153 { "clear", (PyCFunction) pyprocess_clear,
154 METH_VARARGS|METH_KEYWORDS, pyprocess_clear__doc__ },
155 { "abandon_latest", (PyCFunction) pyprocess_abandon_latest,
156 METH_VARARGS|METH_KEYWORDS, pyprocess_abandon_latest__doc__ },
157 { NULL, NULL, 0, NULL }
158 };
160 PyMODINIT_FUNC
161 initprocess(void)
162 {
163 Py_InitModule("process", pyprocess_module_methods);
164 }