# HG changeset patch # User Tim Deegan # Date 1274870633 -3600 # Node ID 3ec63b9937079339144b69e11eaf154481394c73 # Parent dd3036bde0a56e9629b1d9f9d8570137d1e509f4 Make sure that libxenstore reports an error if xenstored drops the connection, rather than getting stuck forever. Patch from: Steven Smith Signed-off-by: Tim Deegan diff -r dd3036bde0a5 -r 3ec63b993707 tools/xenstore/xs.c --- a/tools/xenstore/xs.c Wed May 26 11:41:12 2010 +0100 +++ b/tools/xenstore/xs.c Wed May 26 11:43:53 2010 +0100 @@ -94,6 +94,8 @@ */ #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 @@ #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 @@ { 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 @@ 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 @@ 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