From 27b55337ce43a816f7e0b99183c1a9ad31aa869c Mon Sep 17 00:00:00 2001 From: Christine Caulfield Date: Tue, 4 Aug 2009 07:14:55 +0000 Subject: [PATCH] This patch makes a copy of the notifications list before calling the reload_notifications callbacks. This allows callback functions to manipulate the notifications list without causing corruption or strange loops. git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@2380 fd59a12c-fef9-0310-b244-a6a79926bd2f --- exec/objdb.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/exec/objdb.c b/exec/objdb.c index 2e0e3296..33688cba 100644 --- a/exec/objdb.c +++ b/exec/objdb.c @@ -326,24 +326,43 @@ static void object_key_changed_notification(hdb_handle_t object_handle, static void object_reload_notification(int startstop, int flush) { - struct list_head * list; + struct list_head * list, *tmp; + struct list_head tmplist; struct object_instance * obj_pt; struct object_tracker * tracker_pt; + struct object_tracker * tmptracker_pt; unsigned int res; res = hdb_handle_get (&object_instance_database, OBJECT_PARENT_HANDLE, (void *)&obj_pt); + /* + * Make a copy of the list + * so that items can be added & removed in the callbacks + */ + list_init(&tmplist); for (list = obj_pt->track_head.next; list != &obj_pt->track_head; list = list->next) { tracker_pt = list_entry (list, struct object_tracker, object_list); - if (tracker_pt->object_reload_notify_fn != NULL) { - tracker_pt->object_reload_notify_fn(startstop, flush, - tracker_pt->data_pt); + tmptracker_pt = malloc(sizeof(*tracker_pt)); + if (tmptracker_pt) { + list_add(&tmptracker_pt->object_list, &tmplist); + tmptracker_pt->object_reload_notify_fn = tracker_pt->object_reload_notify_fn; + } } } + + for (list = tmplist.next, tmp = list->next; + list != tmplist.prev; list = tmp, tmp = list->next) { + + tracker_pt = list_entry (list, struct object_tracker, object_list); + + tracker_pt->object_reload_notify_fn(startstop, flush, + tracker_pt->data_pt); + free(tracker_pt); + } hdb_handle_put (&object_instance_database, OBJECT_PARENT_HANDLE); }