WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] tools/xenstore: libxenstore: fix threadin

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] tools/xenstore: libxenstore: fix threading bug which cause xend startup hang
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 10 Sep 2010 14:40:47 -0700
Delivery-date: Fri, 10 Sep 2010 14:45:18 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
# Date 1284141993 -3600
# Node ID 3985fea87987a5061573ab7f6b13cd885261830a
# Parent  f694fdd471ec51e7e3b1422d3617848d70ac2832
tools/xenstore: libxenstore: fix threading bug which cause xend startup hang

If a multithreaded caller creates a thread which calls xs_read_watch,
before it has set any watches with xs_watch, the thread in
xs_read_watch will enter read_message and sit reading the xenstored fd
without the appropriate locks held.  Other threads can then
concurrently read the xenstored fd, which naturally does not work very
well.

Symptoms of this bug which I have been able to reproduce include
failure of xend startup to finish, due to a deadlock; results could
also include reading corrupted data from xenstore.

In this patch we arrange for xs_read_watch to always rely on the
reader thread created by xs_watch.  If no watches have been set, then
xs_read_watch will block until one has been.  If the library is
compiled non-threaded xs_read_watch unconditionally does the reading
in the current thread.

Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
 tools/xenstore/xs.c |   44 ++++++++++++++++++++++++++++++++++----------
 1 files changed, 34 insertions(+), 10 deletions(-)

diff -r f694fdd471ec -r 3985fea87987 tools/xenstore/xs.c
--- a/tools/xenstore/xs.c       Fri Sep 10 19:01:31 2010 +0100
+++ b/tools/xenstore/xs.c       Fri Sep 10 19:06:33 2010 +0100
@@ -79,6 +79,20 @@ struct xs_handle {
 
        /* One request at a time. */
        pthread_mutex_t request_mutex;
+
+       /* Lock discipline:
+        *  Only holder of the request lock may write to h->fd.
+        *  Only holder of the request lock may access read_thr_exists.
+        *  If read_thr_exists==0, only holder of request lock may read h->fd;
+        *  If read_thr_exists==1, only the read thread may read h->fd.
+        *  Only holder of the reply lock may access reply_list.
+        *  Only holder of the watch lock may access watch_list.
+        * Lock hierarchy:
+        *  The order in which to acquire locks is
+        *     request_mutex
+        *     reply_mutex
+        *     watch_mutex
+        */
 };
 
 #define mutex_lock(m)          pthread_mutex_lock(m)
@@ -662,21 +676,27 @@ char **xs_read_watch(struct xs_handle *h
        struct xs_stored_msg *msg;
        char **ret, *strings, c = 0;
        unsigned int num_strings, i;
-       int read_from_thread;
-
-       read_from_thread = read_thread_exists(h);
-
-       /* Read from comms channel ourselves if there is no reader thread. */
-       if (!read_from_thread && (read_message(h) == -1))
-               return NULL;
 
        mutex_lock(&h->watch_mutex);
 
-       /* Wait on the condition variable for a watch to fire. */
 #ifdef USE_PTHREAD
-       while (list_empty(&h->watch_list) && read_from_thread && h->fd != -1)
+       /* Wait on the condition variable for a watch to fire.
+        * If the reader thread doesn't exist yet, then that's because
+        * we haven't called xs_watch.  Presumably the application
+        * will do so later; in the meantime we just block.
+        */
+       while (list_empty(&h->watch_list) && h->fd != -1)
                condvar_wait(&h->watch_condvar, &h->watch_mutex);
-#endif
+#else /* !defined(USE_PTHREAD) */
+       /* Read from comms channel ourselves if there are no threads
+        * and therefore no reader thread. */
+
+       assert(!read_thread_exists(h)); /* not threadsafe but worth a check */
+       if ((read_message(h) == -1))
+               return NULL;
+
+#endif /* !defined(USE_PTHREAD) */
+
        if (list_empty(&h->watch_list)) {
                mutex_unlock(&h->watch_mutex);
                errno = EINVAL;
@@ -900,6 +920,10 @@ char *xs_debug_command(struct xs_handle 
 
 static int read_message(struct xs_handle *h)
 {
+       /* IMPORTANT: It is forbidden to call this function without
+        * acquiring the request lock and checking that h->read_thr_exists
+        * is false.  See "Lock discipline" in struct xs_handle, above. */
+         
        struct xs_stored_msg *msg = NULL;
        char *body = NULL;
        int saved_errno = 0;

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] tools/xenstore: libxenstore: fix threading bug which cause xend startup hang, Xen patchbot-unstable <=