* nih/main.h (NihMainLoopFunc): Add delete member.
* nih/main.c (nih_main_loop): Don't run the callback for any function
marked for deletion, instead call nih_free on it.
(nih_main_loop_add_func): Initialise delete to FALSE.
* nih/dbus.c (nih_dbus_release_callback): Add function to mark a
loop function as deleted.
(nih_dbus_setup): and use it as the free function instead of nih_free.
* nih/tests/test_dbus.c (test_connect, test_bus, test_setup): Check
that the loop functions are marked for deletion instead of freed.

* nih/nih_dbus_tool.py (Output.sourceFile): Include limits.h
diff --git a/ChangeLog b/ChangeLog
index 7f09001..7f89d80 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2008-08-12  Casey Dahlin  <cdahlin@redhat.com>
+
+	* nih/main.h (NihMainLoopFunc): Add delete member.
+	* nih/main.c (nih_main_loop): Don't run the callback for any function
+	marked for deletion, instead call nih_free on it.
+	(nih_main_loop_add_func): Initialise delete to FALSE.
+	* nih/dbus.c (nih_dbus_release_callback): Add function to mark a
+	loop function as deleted.
+	(nih_dbus_setup): and use it as the free function instead of nih_free.
+	* nih/tests/test_dbus.c (test_connect, test_bus, test_setup): Check
+	that the loop functions are marked for deletion instead of freed.
+
+	* nih/nih_dbus_tool.py (Output.sourceFile): Include limits.h
+
 2008-07-02  Scott James Remnant  <scott@netsplit.com>
 
 	* nih/Makefile.am (test_com_netsplit_Nih_Test_object_SOURCES)
diff --git a/nih/dbus.c b/nih/dbus.c
index 3c55282..814caf4 100644
--- a/nih/dbus.c
+++ b/nih/dbus.c
@@ -82,6 +82,7 @@
 						     DBusMessage *message,
 						     NihDBusObject *object);
 static int               nih_dbus_message_destroy   (NihDBusMessage *msg);
+static void              nih_dbus_release_callback  (NihMainLoopFunc *func);
 
 
 /**
@@ -292,6 +293,18 @@
 }
 
 /**
+ * nih_dbus_release_callback:
+ * @func: main loop callback function
+ *
+ * Mark a dbus callback in the main loop deleted.
+ **/
+static void
+nih_dbus_release_callback (NihMainLoopFunc *func)
+{
+	func->delete = TRUE;
+}
+
+/**
  * nih_dbus_setup:
  * @conn: D-Bus connection to setup,
  * @disconnect_handler: function to call on disconnection.
@@ -335,7 +348,7 @@
 		return -1;
 
 	if (! dbus_connection_set_data (conn, main_loop_slot, loop,
-					(DBusFreeFunction)nih_free)) {
+					(DBusFreeFunction)nih_dbus_release_callback)) {
 		nih_free (loop);
 		return -1;
 	}
diff --git a/nih/main.c b/nih/main.c
index 45ff36f..a010e2f 100644
--- a/nih/main.c
+++ b/nih/main.c
@@ -617,7 +617,11 @@
 		NIH_LIST_FOREACH_SAFE (nih_main_loop_functions, iter) {
 			NihMainLoopFunc *func = (NihMainLoopFunc *)iter;
 
-			func->callback (func->data, func);
+			if (! func->delete) {
+				func->callback (func->data, func);
+			} else {
+				nih_free (iter);
+			}
 		}
 	}
 
@@ -702,6 +706,8 @@
 	func->callback = callback;
 	func->data = data;
 
+	func->delete = FALSE;
+
 	nih_list_add (nih_main_loop_functions, &func->entry);
 
 	return func;
diff --git a/nih/main.h b/nih/main.h
index bd5887c..f827ce9 100644
--- a/nih/main.h
+++ b/nih/main.h
@@ -44,6 +44,7 @@
  * @entry: list header,
  * @callback: function called,
  * @data: pointer passed to @callback.
+ * @delete: the function should be freed instead of run.
  *
  * This structure contains information about a function that should be
  * called once in each main loop iteration.
@@ -56,6 +57,8 @@
 
 	NihMainLoopCb  callback;
 	void          *data;
+
+	int            delete;
 };
 
 
diff --git a/nih/nih_dbus_tool.py b/nih/nih_dbus_tool.py
index 1dbf5b8..e998578 100644
--- a/nih/nih_dbus_tool.py
+++ b/nih/nih_dbus_tool.py
@@ -1828,6 +1828,7 @@
 #include <dbus/dbus.h>
 
 #include <errno.h>
+#include <limits.h>
 
 #include <nih/macros.h>
 #include <nih/alloc.h>
diff --git a/nih/tests/test_dbus.c b/nih/tests/test_dbus.c
index 6a25954..568944a 100644
--- a/nih/tests/test_dbus.c
+++ b/nih/tests/test_dbus.c
@@ -212,7 +212,10 @@
 	TEST_TRUE (disconnected);
 	TEST_EQ_P (last_connection, conn);
 
-	TEST_FREE (loop_func);
+	TEST_NOT_FREE (loop_func);
+	TEST_TRUE (loop_func->delete);
+
+	nih_free (loop_func);
 
 
 	/* Check that by using a GUID we can reuse connections to the same
@@ -296,7 +299,10 @@
 	TEST_TRUE (disconnected);
 	TEST_EQ_P (last_connection, conn);
 
-	TEST_FREE (loop_func);
+	TEST_NOT_FREE (loop_func);
+	TEST_TRUE (loop_func->delete);
+
+	nih_free (loop_func);
 
 
 	/* Check that we can create a new connection to a listening dbus
@@ -328,6 +334,14 @@
 	TEST_TRUE (disconnected);
 	TEST_EQ_P (last_connection, conn);
 
+	/* Reap deleted */
+	NIH_LIST_FOREACH_SAFE (nih_main_loop_functions, iter) {
+		NihMainLoopFunc *func = (NihMainLoopFunc *)iter;
+
+		if (func->delete)
+			nih_free (func);
+	}
+
 
 	/* Check that if we create a new connection to a non-listening
 	 * address, no object is returned.
@@ -356,7 +370,7 @@
 	DBusServer      *server;
 	DBusConnection  *conn, *last_conn;
 	NihIoWatch      *io_watch;
-	NihMainLoopFunc *loop_func;
+	NihMainLoopFunc *loop_func = NULL;
 	NihError        *err;
 	pid_t            pid1, pid2;
 	int              fd, wait_fd, status;
@@ -399,10 +413,18 @@
 
 	TEST_EQ_P (loop_func->data, conn);
 
+	TEST_FREE_TAG (loop_func);
+
 	dbus_connection_unref (conn);
 system_bus:
 	dbus_shutdown ();
 
+	if (loop_func) {
+		TEST_NOT_FREE (loop_func);
+		TEST_TRUE (loop_func->delete);
+		nih_free (loop_func);
+	}
+
 
 	/* Check that we can create a connection to the D-Bus system bus,
 	 * the returned object should be hooked up to the main loop.
@@ -423,6 +445,16 @@
 	TEST_EQ (io_watch->fd, fd);
 	TEST_NE_P (io_watch->data, NULL);
 
+#if 0
+	/* Reap deleted */
+	NIH_LIST_FOREACH_SAFE (nih_main_loop_functions, iter) {
+		NihMainLoopFunc *fn = (NihMainLoopFunc *)iter;
+
+		if (fn->marked_deleted)
+			nih_free (fn);
+	}
+#endif
+
 	/* Should be a single main loop function. */
 	TEST_LIST_NOT_EMPTY (nih_main_loop_functions);
 	loop_func = (NihMainLoopFunc *)nih_main_loop_functions->next;
@@ -430,9 +462,15 @@
 
 	TEST_EQ_P (loop_func->data, conn);
 
+	TEST_FREE_TAG (loop_func);
+
 	dbus_connection_unref (conn);
 	dbus_shutdown ();
 
+	TEST_NOT_FREE (loop_func);
+	TEST_TRUE (loop_func->delete);
+	nih_free (loop_func);
+
 
 	/* Check that we can share connections to a bus. */
 	TEST_FEATURE ("with shared bus connection");
@@ -451,6 +489,16 @@
 	TEST_EQ (io_watch->fd, fd);
 	TEST_NE_P (io_watch->data, NULL);
 
+#if 0
+	/* Reap deleted */
+	NIH_LIST_FOREACH_SAFE (nih_main_loop_functions, iter) {
+		NihMainLoopFunc *fn = (NihMainLoopFunc *)iter;
+
+		if (fn->marked_deleted)
+			nih_free (fn);
+	}
+#endif
+
 	/* Should be a single main loop function. */
 	TEST_LIST_NOT_EMPTY (nih_main_loop_functions);
 	loop_func = (NihMainLoopFunc *)nih_main_loop_functions->next;
@@ -475,6 +523,7 @@
 
 	/* Should be the same main loop function. */
 	TEST_NOT_FREE (loop_func);
+	TEST_FALSE (loop_func->delete);
 	TEST_LIST_NOT_EMPTY (nih_main_loop_functions);
 	TEST_EQ_P (nih_main_loop_functions->next, &loop_func->entry);
 	TEST_EQ_P (loop_func->entry.next, nih_main_loop_functions);
@@ -484,6 +533,10 @@
 	dbus_connection_unref (last_conn);
 	dbus_shutdown ();
 
+	TEST_NOT_FREE (loop_func);
+	TEST_TRUE (loop_func->delete);
+	nih_free (loop_func);
+
 
 	/* Check that if the bus disconnects before registration, NULL
 	 * is returned along with an error.  Stock dbus tends to bail out
@@ -596,6 +649,16 @@
 	TEST_EQ (io_watch->fd, fd);
 	TEST_NE_P (io_watch->data, NULL);
 
+#if 0
+	/* Reap deleted */
+	NIH_LIST_FOREACH_SAFE (nih_main_loop_functions, iter) {
+		NihMainLoopFunc *fn = (NihMainLoopFunc *)iter;
+
+		if (fn->marked_deleted)
+			nih_free (fn);
+	}
+#endif
+
 	/* Should be a single main loop function. */
 	TEST_LIST_NOT_EMPTY (nih_main_loop_functions);
 	loop_func = (NihMainLoopFunc *)nih_main_loop_functions->next;
@@ -625,6 +688,7 @@
 
 	/* Should be the same main loop function. */
 	TEST_NOT_FREE (loop_func);
+	TEST_FALSE (loop_func->delete);
 	TEST_LIST_NOT_EMPTY (nih_main_loop_functions);
 	TEST_EQ_P (nih_main_loop_functions->next, &loop_func->entry);
 	TEST_EQ_P (loop_func->entry.next, nih_main_loop_functions);
@@ -632,6 +696,10 @@
 
 	dbus_connection_unref (conn);
 	dbus_shutdown ();
+
+	TEST_NOT_FREE (loop_func);
+	TEST_TRUE (loop_func->delete);
+	nih_free (loop_func);
 }