aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xenstore/xenstored_watch.c
diff options
context:
space:
mode:
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>2005-07-26 15:26:32 +0000
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>2005-07-26 15:26:32 +0000
commiteb825f79cb6e0939871180692808f241fe5ddc93 (patch)
tree5b67c7f5cb99233e1f683f53266e594f74218c77 /tools/xenstore/xenstored_watch.c
parentdfc7e02e7ab3715f098e8a6c4105016b0862c5df (diff)
downloadxen-eb825f79cb6e0939871180692808f241fe5ddc93.tar.gz
xen-eb825f79cb6e0939871180692808f241fe5ddc93.tar.bz2
xen-eb825f79cb6e0939871180692808f241fe5ddc93.zip
Remove ill-conceived concept of watches blocking reply on
connection which did write/mkdir/rm/setperm etc. This causes deadlocks in real life, and I can't see a sane way of avoiding them: it is reasonable for someone to ignore watch notifications while doing other actions, and that means that we can do other writes. These writes can block pending other watchers; if one of these is the process blocked awaiting our ack, we deadlock. Signed-off-by: Rusty Russel <rusty@rustcorp.com.au> Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
Diffstat (limited to 'tools/xenstore/xenstored_watch.c')
-rw-r--r--tools/xenstore/xenstored_watch.c21
1 files changed, 5 insertions, 16 deletions
diff --git a/tools/xenstore/xenstored_watch.c b/tools/xenstore/xenstored_watch.c
index a49dcbc954..1c42b72ced 100644
--- a/tools/xenstore/xenstored_watch.c
+++ b/tools/xenstore/xenstored_watch.c
@@ -41,9 +41,6 @@ struct watch_event
/* Data to send (node\0token\0). */
unsigned int len;
char *data;
-
- /* Connection which caused watch event (which we are blocking) */
- struct connection *cause;
};
struct watch
@@ -95,14 +92,10 @@ static int destroy_watch_event(void *_event)
struct watch_event *event = _event;
trace_destroy(event, "watch_event");
- assert(event->cause->watches_unacked != 0);
- /* If it hits zero, will unblock in unblock_connections. */
- event->cause->watches_unacked--;
return 0;
}
-static void add_event(struct connection *cause, struct watch *watch,
- const char *node)
+static void add_event(struct watch *watch, const char *node)
{
struct watch_event *event;
@@ -117,22 +110,20 @@ static void add_event(struct connection *cause, struct watch *watch,
event->data = talloc_array(event, char, event->len);
strcpy(event->data, node);
strcpy(event->data + strlen(node) + 1, watch->token);
- event->cause = cause;
- cause->watches_unacked++;
talloc_set_destructor(event, destroy_watch_event);
list_add_tail(&event->list, &watch->events);
trace_create(event, "watch_event");
}
/* FIXME: we fail to fire on out of memory. Should drop connections. */
-bool fire_watches(struct connection *conn, const char *node, bool recurse)
+void fire_watches(struct connection *conn, const char *node, bool recurse)
{
struct connection *i;
struct watch *watch;
/* During transactions, don't fire watches. */
if (conn->transaction)
- return false;
+ return;
/* Create an event for each watch. Don't send to self. */
list_for_each_entry(i, &connections, list) {
@@ -141,18 +132,16 @@ bool fire_watches(struct connection *conn, const char *node, bool recurse)
list_for_each_entry(watch, &i->watches, list) {
if (is_child(node, watch->node))
- add_event(conn, watch, node);
+ add_event(watch, node);
else if (recurse && is_child(watch->node, node))
- add_event(conn, watch, watch->node);
+ add_event(watch, watch->node);
else
continue;
- conn->state = WATCHED;
/* If connection not doing anything, queue this. */
if (!i->out)
queue_next_event(i);
}
}
- return conn->state == WATCHED;
}
static int destroy_watch(void *_watch)