diff options
author | cl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk> | 2005-07-26 15:26:32 +0000 |
---|---|---|
committer | cl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk> | 2005-07-26 15:26:32 +0000 |
commit | eb825f79cb6e0939871180692808f241fe5ddc93 (patch) | |
tree | 5b67c7f5cb99233e1f683f53266e594f74218c77 /tools/xenstore/xenstored_watch.c | |
parent | dfc7e02e7ab3715f098e8a6c4105016b0862c5df (diff) | |
download | xen-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.c | 21 |
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) |