diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2010-06-04 10:36:29 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2010-06-04 10:36:29 +0100 |
commit | 22d682f05da7b8714a2808d1c0bf4b3883b05fc6 (patch) | |
tree | 50d033d012ef0889b41cdb398fd98e35de551b76 | |
parent | 2423f73fe2aca08e222ab2c6541c3fbc0c1ac496 (diff) | |
download | xen-22d682f05da7b8714a2808d1c0bf4b3883b05fc6.tar.gz xen-22d682f05da7b8714a2808d1c0bf4b3883b05fc6.tar.bz2 xen-22d682f05da7b8714a2808d1c0bf4b3883b05fc6.zip |
xenstore: Make sure that libxs reports an error if xenstored drops
the connection, rather than getting stuck forever.
Patch from: Steven Smith <steven.smith@eu.citrix.com>
Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
xen-unstable changeset: 21463:5be2d2a7f445
xen-unstable date: Thu May 27 08:20:26 2010 +0100
-rw-r--r-- | tools/xenstore/xs.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/tools/xenstore/xs.c b/tools/xenstore/xs.c index 58c6f93574..6dbdfd703a 100644 --- a/tools/xenstore/xs.c +++ b/tools/xenstore/xs.c @@ -94,6 +94,8 @@ struct xs_handle { */ #define cleanup_pop(run) ((void)0); pthread_cleanup_pop(run) +#define read_thread_exists(h) (h->read_thr_exists) + static void *read_thread(void *arg); #else /* !defined(USE_PTHREAD) */ @@ -112,6 +114,7 @@ struct xs_handle { #define condvar_wait(c,m,hnd) read_message(hnd) #define cleanup_push(f, a) ((void)0) #define cleanup_pop(run) ((void)0) +#define read_thread_exists(h) (0) #endif @@ -316,16 +319,25 @@ static void *read_reply( { struct xs_stored_msg *msg; char *body; + int read_from_thread; + + read_from_thread = read_thread_exists(h); #ifdef USE_PTHREAD /* Read from comms channel ourselves if there is no reader thread. */ - if (!h->read_thr_exists && (read_message(h) == -1)) + if (!read_from_thread && (read_message(h) == -1)) return NULL; #endif mutex_lock(&h->reply_mutex); - while (list_empty(&h->reply_list)) + 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)) { + 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)); @@ -633,8 +645,13 @@ char **xs_read_watch(struct xs_handle *h, unsigned int *num) mutex_lock(&h->watch_mutex); /* Wait on the condition variable for a watch to fire. */ - while (list_empty(&h->watch_list)) + while (list_empty(&h->watch_list) && read_thread_exists(h)) condvar_wait(&h->watch_condvar, &h->watch_mutex, h); + if (!read_thread_exists(h)) { + mutex_unlock(&h->watch_mutex); + errno = EINVAL; + return NULL; + } msg = list_top(&h->watch_list, struct xs_stored_msg, list); list_del(&msg->list); @@ -930,6 +947,19 @@ static void *read_thread(void *arg) 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); + + pthread_mutex_lock(&h->reply_mutex); + pthread_cond_signal(&h->reply_condvar); + pthread_mutex_unlock(&h->reply_mutex); + + pthread_mutex_lock(&h->watch_mutex); + pthread_cond_signal(&h->watch_condvar); + pthread_mutex_unlock(&h->watch_mutex); + return NULL; } #endif |