aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xenstore
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-05-27 08:20:26 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-05-27 08:20:26 +0100
commita705c154283a30d632450773d6ce5e1f307874a7 (patch)
tree30b0d9bcfb3e8ed6475abd07cfb2bee80c02f42e /tools/xenstore
parentf4f16d740c0b400b75d7ce223f55d08b61445220 (diff)
downloadxen-a705c154283a30d632450773d6ce5e1f307874a7.tar.gz
xen-a705c154283a30d632450773d6ce5e1f307874a7.tar.bz2
xen-a705c154283a30d632450773d6ce5e1f307874a7.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>
Diffstat (limited to 'tools/xenstore')
-rw-r--r--tools/xenstore/xs.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/tools/xenstore/xs.c b/tools/xenstore/xs.c
index 7e3d9c4b63..094db25efa 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
@@ -330,16 +333,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));
@@ -647,8 +659,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);
@@ -944,6 +961,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