mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
Make libxenstore thread-safe. It also spawns an internal
thread to read messages from the comms channel. Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
47f583a947
commit
7429d6e032
14 files changed
+300
-306
No files matched your search
@@ -775,39 +775,6 @@ static PyObject *xspy_close(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
return val;
|
||||
}
|
||||
|
||||
#define xspy_shutdown_doc "\n" \
|
||||
"Shutdown the xenstore daemon.\n" \
|
||||
"\n" \
|
||||
"Returns None on success.\n" \
|
||||
"Raises RuntimeError on error.\n" \
|
||||
"\n"
|
||||
|
||||
static PyObject *xspy_shutdown(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwd_spec[] = { NULL };
|
||||
static char *arg_spec = "";
|
||||
|
||||
struct xs_handle *xh = xshandle(self);
|
||||
PyObject *val = NULL;
|
||||
int xsval = 0;
|
||||
|
||||
if (!xh)
|
||||
goto exit;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
|
||||
goto exit;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
xsval = xs_shutdown(xh);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (!xsval) {
|
||||
PyErr_SetFromErrno(PyExc_RuntimeError);
|
||||
goto exit;
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
val = Py_None;
|
||||
exit:
|
||||
return val;
|
||||
}
|
||||
|
||||
#define xspy_get_domain_path_doc "\n" \
|
||||
"Return store path of domain.\n" \
|
||||
" domid [int]: domain id\n" \
|
||||
@@ -850,28 +817,6 @@ static PyObject *xspy_get_domain_path(PyObject *self, PyObject *args,
|
||||
return val;
|
||||
}
|
||||
|
||||
#define xspy_fileno_doc "\n" \
|
||||
"Get the file descriptor of the xenstore socket.\n" \
|
||||
"Allows an xs object to be passed to select().\n" \
|
||||
"\n" \
|
||||
"Returns: [int] file descriptor.\n" \
|
||||
"\n"
|
||||
|
||||
static PyObject *xspy_fileno(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwd_spec[] = { NULL };
|
||||
static char *arg_spec = "";
|
||||
|
||||
struct xs_handle *xh = xshandle(self);
|
||||
PyObject *val = NULL;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
|
||||
goto exit;
|
||||
val = PyInt_FromLong((xh ? xs_fileno(xh) : -1));
|
||||
exit:
|
||||
return val;
|
||||
}
|
||||
|
||||
#define XSPY_METH(_name) { \
|
||||
.ml_name = #_name, \
|
||||
.ml_meth = (PyCFunction) xspy_ ## _name, \
|
||||
@@ -895,9 +840,7 @@ static PyMethodDef xshandle_methods[] = {
|
||||
XSPY_METH(introduce_domain),
|
||||
XSPY_METH(release_domain),
|
||||
XSPY_METH(close),
|
||||
XSPY_METH(shutdown),
|
||||
XSPY_METH(get_domain_path),
|
||||
XSPY_METH(fileno),
|
||||
{ /* Terminator. */ },
|
||||
};
|
||||
|
||||
|
||||
@@ -7,14 +7,17 @@
|
||||
import threading
|
||||
from xen.lowlevel import xs
|
||||
|
||||
handles = {}
|
||||
xs_lock = threading.Lock()
|
||||
xs_handle = None
|
||||
|
||||
# XXX need to g/c handles from dead threads
|
||||
def xshandle():
|
||||
if not handles.has_key(threading.currentThread()):
|
||||
handles[threading.currentThread()] = xs.open()
|
||||
return handles[threading.currentThread()]
|
||||
|
||||
global xs_handle, xs_lock
|
||||
if not xs_handle:
|
||||
xs_lock.acquire()
|
||||
if not xs_handle:
|
||||
xs_handle = xs.open()
|
||||
xs_lock.release()
|
||||
return xs_handle
|
||||
|
||||
def IntroduceDomain(domid, page, port, path):
|
||||
return xshandle().introduce_domain(domid, page, port, path)
|
||||
|
||||
@@ -12,7 +12,6 @@ from xen.lowlevel import xs
|
||||
class xswatch:
|
||||
|
||||
watchThread = None
|
||||
threadcond = threading.Condition()
|
||||
xs = None
|
||||
xslock = threading.Lock()
|
||||
|
||||
@@ -21,43 +20,31 @@ class xswatch:
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
xswatch.watchStart()
|
||||
xswatch.xslock.acquire()
|
||||
xswatch.xs.watch(path, self)
|
||||
xswatch.xslock.release()
|
||||
|
||||
def watchStart(cls):
|
||||
cls.threadcond.acquire()
|
||||
cls.xslock.acquire()
|
||||
if cls.watchThread:
|
||||
cls.threadcond.release()
|
||||
cls.xslock.release()
|
||||
return
|
||||
# XXX: When we fix xenstored to have better watch semantics,
|
||||
# this can change to shared xshandle(). Currently that would result
|
||||
# in duplicate watch firings, thus failed extra xs.acknowledge_watch.
|
||||
cls.xs = xs.open()
|
||||
cls.watchThread = threading.Thread(name="Watcher",
|
||||
target=cls.watchMain)
|
||||
cls.watchThread.setDaemon(True)
|
||||
cls.watchThread.start()
|
||||
while cls.xs == None:
|
||||
cls.threadcond.wait()
|
||||
cls.threadcond.release()
|
||||
cls.xslock.release()
|
||||
|
||||
watchStart = classmethod(watchStart)
|
||||
|
||||
def watchMain(cls):
|
||||
cls.threadcond.acquire()
|
||||
cls.xs = xs.open()
|
||||
cls.threadcond.notifyAll()
|
||||
cls.threadcond.release()
|
||||
while True:
|
||||
try:
|
||||
(fd, _1, _2) = select.select([ cls.xs ], [], [])
|
||||
cls.xslock.acquire()
|
||||
# reconfirm ready to read with lock
|
||||
(fd, _1, _2) = select.select([ cls.xs ], [], [], 0.001)
|
||||
if not cls.xs in fd:
|
||||
cls.xslock.release()
|
||||
continue
|
||||
we = cls.xs.read_watch()
|
||||
watch = we[1]
|
||||
cls.xs.acknowledge_watch(watch)
|
||||
cls.xslock.release()
|
||||
except RuntimeError, ex:
|
||||
print ex
|
||||
raise
|
||||
|
||||