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

[Xen-changelog] [xen-unstable] tools/xenstore: correctly handle errors from read_message



# HG changeset patch
# User Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>
# Date 1283348238 -3600
# Node ID 20e01ec42aabac99fa4ff2d5db630a04d4bc6820
# Parent  eff592364826a7361b6d72adca596c5ee2331840
tools/xenstore: correctly handle errors from read_message

The return value of read_message needs to be checked in order to avoid
waiting forever for a message if there is an error on the communication
channel with xenstore. Currently, this is only checked if USE_PTHREAD is
defined (by checking for read thread exit), and that path is prone to
deadlock if request_mutex is held while waiting.

Since the failure of read_message leaves the socket in an undefined
state, close the socket and force all threads waiting on a read to return.

This also fixes xs_read_watch in the case where a read thread is not
running (in particular, this will happen if !USE_PTHREAD) by having it
read from the communication channel in the same way as read_reply.

Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>
Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
---
 tools/xenstore/xs.c |   52 +++++++++++++++++++++++++++++++++-------------------
 1 files changed, 33 insertions(+), 19 deletions(-)

diff -r eff592364826 -r 20e01ec42aab tools/xenstore/xs.c
--- a/tools/xenstore/xs.c       Wed Sep 01 11:23:49 2010 +0100
+++ b/tools/xenstore/xs.c       Wed Sep 01 14:37:18 2010 +0100
@@ -84,7 +84,7 @@ struct xs_handle {
 #define mutex_lock(m)          pthread_mutex_lock(m)
 #define mutex_unlock(m)                pthread_mutex_unlock(m)
 #define condvar_signal(c)      pthread_cond_signal(c)
-#define condvar_wait(c,m,hnd)  pthread_cond_wait(c,m)
+#define condvar_wait(c,m)      pthread_cond_wait(c,m)
 #define cleanup_push(f, a)     \
     pthread_cleanup_push((void (*)(void *))(f), (void *)(a))
 /*
@@ -111,7 +111,7 @@ struct xs_handle {
 #define mutex_lock(m)          ((void)0)
 #define mutex_unlock(m)                ((void)0)
 #define condvar_signal(c)      ((void)0)
-#define condvar_wait(c,m,hnd)  read_message(hnd)
+#define condvar_wait(c,m)      ((void)0)
 #define cleanup_push(f, a)     ((void)0)
 #define cleanup_pop(run)       ((void)0)
 #define read_thread_exists(h)  (0)
@@ -337,21 +337,20 @@ static void *read_reply(
 
        read_from_thread = read_thread_exists(h);
 
-#ifdef USE_PTHREAD
        /* Read from comms channel ourselves if there is no reader thread. */
        if (!read_from_thread && (read_message(h) == -1))
                return NULL;
+
+       mutex_lock(&h->reply_mutex);
+#ifdef USE_PTHREAD
+       while (list_empty(&h->reply_list) && read_from_thread && h->fd != -1)
+               condvar_wait(&h->reply_condvar, &h->reply_mutex);
 #endif
-
-       mutex_lock(&h->reply_mutex);
-       while (list_empty(&h->reply_list) && (!read_from_thread || 
read_thread_exists(h)))
-               condvar_wait(&h->reply_condvar, &h->reply_mutex, h);
-       if (read_from_thread && !read_thread_exists(h)) {
+       if (list_empty(&h->reply_list)) {
                mutex_unlock(&h->reply_mutex);
                errno = EINVAL;
                return NULL;
        }
-       assert(!list_empty(&h->reply_list));
        msg = list_top(&h->reply_list, struct xs_stored_msg, list);
        list_del(&msg->list);
        assert(list_empty(&h->reply_list));
@@ -663,13 +662,22 @@ 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. */
-       while (list_empty(&h->watch_list) && read_thread_exists(h))
-               condvar_wait(&h->watch_condvar, &h->watch_mutex, h);
-       if (!read_thread_exists(h)) {
+#ifdef USE_PTHREAD
+       while (list_empty(&h->watch_list) && read_from_thread && h->fd != -1)
+               condvar_wait(&h->watch_condvar, &h->watch_mutex);
+#endif
+       if (list_empty(&h->watch_list)) {
                mutex_unlock(&h->watch_mutex);
                errno = EINVAL;
                return NULL;
@@ -965,21 +973,27 @@ static void *read_thread(void *arg)
 static void *read_thread(void *arg)
 {
        struct xs_handle *h = arg;
+       int fd;
 
        while (read_message(h) != -1)
                continue;
 
-       /* Kick anyone waiting for a reply */
-       pthread_mutex_lock(&h->request_mutex);
-       h->read_thr_exists = 0;
-       pthread_mutex_unlock(&h->request_mutex);
-
+       /* An error return from read_message leaves the socket in an undefined
+        * state; we might have read only the header and not the message after
+        * it, or (more commonly) the other end has closed the connection.
+        * Since further communication is unsafe, close the socket.
+        */
+       fd = h->fd;
+       h->fd = -1;
+       close(fd);
+
+       /* wake up all waiters */
        pthread_mutex_lock(&h->reply_mutex);
-       pthread_cond_signal(&h->reply_condvar);
+       pthread_cond_broadcast(&h->reply_condvar);
        pthread_mutex_unlock(&h->reply_mutex);
 
        pthread_mutex_lock(&h->watch_mutex);
-       pthread_cond_signal(&h->watch_condvar);
+       pthread_cond_broadcast(&h->watch_condvar);
        pthread_mutex_unlock(&h->watch_mutex);
 
        return NULL;

_______________________________________________
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®.