Index: gsignal.c
===================================================================
RCS file: /cvs/gnome/glib/gobject/gsignal.c,v
retrieving revision 1.52
diff -u -p -r1.52 gsignal.c
--- gsignal.c	19 Aug 2003 02:15:40 -0000	1.52
+++ gsignal.c	5 Sep 2003 02:19:12 -0000
@@ -90,6 +90,7 @@ typedef struct _Emission     Emission;
 typedef struct _Handler      Handler;
 typedef struct _HandlerList  HandlerList;
 typedef struct _HandlerMatch HandlerMatch;
+typedef struct _InstanceInfo InstanceInfo;
 typedef enum
 {
   EMISSION_STOP,
@@ -150,6 +151,12 @@ static	      gboolean		signal_emit_unloc
 							 gpointer	  instance,
 							 GValue		 *return_value,
 							 const GValue	 *instance_and_params);
+static       void               instance_info_attach    (GClosure        *closure,
+							 guint            signal_id,
+							 gpointer         instance,
+							 Handler         *handler);
+static       void               invalid_closure_notify  (gpointer         data,
+							 GClosure        *closure);
 static const gchar *            type_debug_name         (GType            type);
 
 
@@ -221,6 +228,7 @@ struct _Handler
 #define HANDLER_MAX_BLOCK_COUNT (1 << 12)
   guint         after : 1;
   GClosure     *closure;
+  InstanceInfo *instance_info;
 };
 struct _HandlerMatch
 {
@@ -231,6 +239,12 @@ struct _HandlerMatch
     gpointer	dummy;
   } d;
 };
+struct _InstanceInfo
+{
+  guint     signal_id;
+  gpointer  instance;
+  Handler  *handler;
+};
 
 typedef struct
 {
@@ -549,6 +563,7 @@ handler_new (gboolean after)
   handler->block_count = 0;
   handler->after = after != FALSE;
   handler->closure = NULL;
+  handler->instance_info = NULL;
   
   return handler;
 }
@@ -587,6 +602,11 @@ handler_unref_R (guint    signal_id,
           hlist->handlers = handler->next;
         }
       SIGNAL_UNLOCK ();
+      if (handler->instance_info)
+	{
+	  g_closure_remove_invalidate_notifier (handler->closure, handler->instance_info, invalid_closure_notify);
+	  g_free (handler->instance_info);
+	}
       g_closure_unref (handler->closure);
       SIGNAL_LOCK ();
       g_generic_node_free (&g_handler_ts, handler);
@@ -1559,6 +1579,7 @@ g_signal_connect_closure_by_id (gpointer
 	  handler->detail = detail;
 	  handler->closure = g_closure_ref (closure);
 	  g_closure_sink (closure);
+	  instance_info_attach (closure, signal_id, instance, handler);
 	  handler_insert (signal_id, instance, handler);
 	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
 	    g_closure_set_marshal (closure, node->c_marshaller);
@@ -1605,6 +1626,7 @@ g_signal_connect_closure (gpointer     i
 	  handler->detail = detail;
 	  handler->closure = g_closure_ref (closure);
 	  g_closure_sink (closure);
+	  instance_info_attach (closure, signal_id, instance, handler);
 	  handler_insert (signal_id, instance, handler);
 	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
 	    g_closure_set_marshal (handler->closure, node->c_marshaller);
@@ -1789,6 +1811,14 @@ g_signal_handlers_destroy (gpointer inst
               tmp->prev = tmp;
               if (tmp->sequential_number)
 		{
+		  if (tmp->instance_info)
+		    {
+		      g_closure_remove_invalidate_notifier (tmp->closure, tmp->instance_info, invalid_closure_notify);
+
+		      g_free (tmp->instance_info);
+		      tmp->instance_info = NULL;
+		    }
+
 		  tmp->sequential_number = 0;
 		  handler_unref_R (0, NULL, tmp);
 		}
@@ -2315,6 +2345,7 @@ signal_emit_unlocked_R (SignalNode   *no
   
   SIGNAL_LOCK ();
   signal_id = node->signal_id;
+
   if (node->flags & G_SIGNAL_NO_RECURSE)
     {
       Emission *node = emission_find (g_restart_emissions, signal_id, detail, instance);
@@ -2572,6 +2603,41 @@ signal_emit_unlocked_R (SignalNode   *no
     g_value_unset (&accu);
   
   return return_value_altered;
+}
+
+static void
+instance_info_attach (GClosure *closure,
+		      guint     signal_id,
+		      gpointer  instance,
+		      Handler  *handler)
+{
+  InstanceInfo *info;
+
+  info = g_new (InstanceInfo, 1);
+
+  info->signal_id = signal_id;
+  info->instance = instance;
+  info->handler = handler;
+
+  handler->instance_info = info;
+
+  g_closure_add_invalidate_notifier (closure, info, invalid_closure_notify);
+}
+
+static void
+invalid_closure_notify (gpointer  data,
+		        GClosure *closure)
+{
+  InstanceInfo *info = data;
+
+  SIGNAL_LOCK ();
+
+  /* GClosure removes our notifier when we're done */
+  info->handler->instance_info = NULL;
+  handler_unref_R (info->signal_id, info->instance, info->handler);
+  g_free (info);
+
+  SIGNAL_UNLOCK ();
 }
 
 static const gchar*
