Просмотр исходного кода

Merge trunk revision 2380:
r2380 | chrissie | 2009-08-04 00:14:55 -0700 (Tue, 04 Aug 2009) | 6 lines

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/branches/flatiron@2432 fd59a12c-fef9-0310-b244-a6a79926bd2f

Steven Dake 16 лет назад
Родитель
Сommit
4cfa49e834
1 измененных файлов с 23 добавлено и 4 удалено
  1. 23 4
      exec/objdb.c

+ 23 - 4
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)
 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_instance * obj_pt;
 	struct object_tracker * tracker_pt;
 	struct object_tracker * tracker_pt;
+	struct object_tracker * tmptracker_pt;
 	unsigned int res;
 	unsigned int res;
 
 
 	res = hdb_handle_get (&object_instance_database,
 	res = hdb_handle_get (&object_instance_database,
 			      OBJECT_PARENT_HANDLE, (void *)&obj_pt);
 			      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;
 	for (list = obj_pt->track_head.next;
 	     list != &obj_pt->track_head; list = list->next) {
 	     list != &obj_pt->track_head; list = list->next) {
 
 
 		tracker_pt = list_entry (list, struct object_tracker, object_list);
 		tracker_pt = list_entry (list, struct object_tracker, object_list);
-
 		if (tracker_pt->object_reload_notify_fn != NULL) {
 		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);
 	hdb_handle_put (&object_instance_database, OBJECT_PARENT_HANDLE);
 }
 }