diff -upr ConsoleKit-0.2.10.orig/src/ck-file-monitor-inotify.c ConsoleKit-0.2.10/src/ck-file-monitor-inotify.c
--- ConsoleKit-0.2.10.orig/src/ck-file-monitor-inotify.c	2008-01-23 15:30:44.000000000 +0100
+++ ConsoleKit-0.2.10/src/ck-file-monitor-inotify.c	2010-07-28 14:13:45.586295961 +0200
@@ -55,9 +55,9 @@ typedef struct
 
 typedef struct
 {
-        FileInotifyWatch  *watch;
-        CkFileMonitorEvent event;
-        char              *path;
+	int			wd;
+	CkFileMonitorEvent	event;
+	char			*path;
 } FileMonitorEventInfo;
 
 #define DEFAULT_NOTIFY_BUFLEN (32 * (sizeof (struct inotify_event) + 16))
@@ -65,22 +65,23 @@ typedef struct
 
 struct CkFileMonitorPrivate
 {
-        guint       serial;
-
-        gboolean    initialized_inotify;
-
-        int         inotify_fd;
-        guint       io_watch;
+	guint		serial;
 
-        GHashTable *wd_to_watch;
-        GHashTable *path_to_watch;
-        GHashTable *notifies;
+	gboolean	initialized_inotify;
 
-        guint       buflen;
-        guchar     *buffer;
+	int		inotify_fd;
+	guint		io_watch;
 
-        guint       events_idle_id;
-        GQueue     *notify_events;
+	GHashTable	*wd_to_watch;
+	GHashTable	*path_to_watch;
+	GHashTable	*notifies;
+
+	guint		buflen;
+	guchar		*buffer;
+	guint		events_idle_id;
+	guint		remove_idle_id;
+	GQueue		*notify_events;
+	GQueue		*remove_events;
 };
 
 enum {
@@ -242,6 +243,10 @@ static void
 file_monitor_remove_watch (CkFileMonitor    *monitor,
                            FileInotifyWatch *watch)
 {
+	if (watch->wd == -1) {
+		return;
+	}
+
         g_hash_table_remove (monitor->priv->path_to_watch,
                              watch->path);
         g_hash_table_remove (monitor->priv->wd_to_watch,
@@ -295,7 +300,9 @@ close_inotify (CkFileMonitor *monitor)
 static gboolean
 emit_events_in_idle (CkFileMonitor *monitor)
 {
-        FileMonitorEventInfo *event_info;
+	FileMonitorEventInfo	*event_info;
+	char			*path;
+	char			*freeme;
 
         monitor->priv->events_idle_id = 0;
 
@@ -303,29 +310,38 @@ emit_events_in_idle (CkFileMonitor *moni
                 GSList           *l;
                 FileInotifyWatch *watch;
 
-                watch = event_info->watch;
-
-                for (l = watch->notifies; l != NULL; l = l->next) {
-                        FileMonitorNotify *notify;
-
-                        notify = g_hash_table_lookup (monitor->priv->notifies,
-                                                      GUINT_TO_POINTER (l->data));
-                        if (notify == NULL) {
-                                continue;
-                        }
-
-                        if (! (notify->mask & event_info->event)) {
-                                continue;
-                        }
-
-                        if (notify->notify_func) {
-                                notify->notify_func (monitor, event_info->event, event_info->path, notify->user_data);
-                        }
+		watch = g_hash_table_lookup (monitor->priv->wd_to_watch,
+						GINT_TO_POINTER (event_info->wd));
+		if (watch != NULL) {
+			for (l = watch->notifies; l != NULL; l = l->next){
+				FileMonitorNotify *notify;
+
+				notify = g_hash_table_lookup (monitor->priv->notifies,
+								GUINT_TO_POINTER (l->data));
+				if (notify == NULL) {
+					continue;
+				}
+
+				if (! (notify->mask & event_info->event)) {
+					continue;
+				}
+
+				if (notify->notify_func) {
+					freeme = NULL;
+					if (event_info->path != NULL) {
+						path = freeme = g_build_filename (watch->path, event_info->path, NULL);
+					} else {
+						path = watch->path;
+					}
+					notify->notify_func (monitor, event_info->event, path, notify->user_data);
+					if (freeme != NULL) {
+						g_free (freeme);
+					}
+				}
+			}
                 }
 
-                g_free (event_info->path);
                 event_info->path = NULL;
-
                 event_info->event = CK_FILE_MONITOR_EVENT_NONE;
 
                 g_free (event_info);
@@ -334,6 +350,36 @@ emit_events_in_idle (CkFileMonitor *moni
         return FALSE;
 }
 
+static gboolean
+emit_removals_in_idle (CkFileMonitor *monitor)
+{
+	gpointer          wd_p;
+	FileInotifyWatch *watch;
+	GSList           *l;
+
+	monitor->priv->remove_idle_id = 0;
+
+	while ((wd_p = g_queue_pop_head (monitor->priv->remove_events)) != NULL) {
+		watch = g_hash_table_lookup (monitor->priv->wd_to_watch, wd_p);
+		if (watch && watch->wd != -1) {
+			for (l = watch->notifies; l != NULL; l = l->next) {
+				FileMonitorNotify *notify;
+
+				notify = g_hash_table_lookup (monitor->priv->notifies,
+								GUINT_TO_POINTER (l->data));
+				if (notify == NULL) {
+					continue;
+				}
+				notify->watch = NULL;
+			}
+			file_monitor_remove_watch (monitor, watch);
+			g_free (watch);
+		}
+	}
+
+	return FALSE;
+}
+
 static void
 file_monitor_queue_event (CkFileMonitor        *monitor,
                           FileMonitorEventInfo *event_info)
@@ -347,7 +393,7 @@ file_monitor_queue_event (CkFileMonitor
 
 static void
 queue_watch_event (CkFileMonitor     *monitor,
-                   FileInotifyWatch  *watch,
+                   int			wd,
                    CkFileMonitorEvent event,
                    const char        *path)
 {
@@ -355,7 +401,7 @@ queue_watch_event (CkFileMonitor     *mo
 
         event_info = g_new0 (FileMonitorEventInfo, 1);
 
-        event_info->watch   = watch;
+        event_info->wd   = wd;
         event_info->path    = g_strdup (path);
         event_info->event   = event;
 
@@ -363,8 +409,18 @@ queue_watch_event (CkFileMonitor     *mo
 }
 
 static void
+queue_remove_event (	CkFileMonitor	*monitor,
+			int		wd)
+{
+	g_queue_push_tail (monitor->priv->remove_events, GINT_TO_POINTER (wd));
+
+	if (monitor->priv->remove_idle_id == 0) {
+		monitor->priv->remove_idle_id = g_idle_add ((GSourceFunc) emit_removals_in_idle, monitor);
+	}
+}
+
+static void
 handle_inotify_event (CkFileMonitor        *monitor,
-                      FileInotifyWatch     *watch,
                       struct inotify_event *ievent)
 {
         CkFileMonitorEvent  event;
@@ -375,9 +431,9 @@ handle_inotify_event (CkFileMonitor
         freeme = NULL;
 
         if (ievent->len > 0) {
-                path = freeme = g_build_filename (watch->path, ievent->name, NULL);
+		path = ievent->name;
         } else {
-                path = watch->path;
+                path = NULL;
         }
 
         mask_str = imask_to_string (ievent->mask);
@@ -397,11 +453,11 @@ handle_inotify_event (CkFileMonitor
         }
 
         if (event != CK_FILE_MONITOR_EVENT_NONE) {
-                queue_watch_event (monitor, watch, event, path);
+                queue_watch_event (monitor, ievent->wd, event, path);
         }
 
         if (ievent->mask & IN_IGNORED) {
-                file_monitor_remove_watch (monitor, watch);
+                queue_remove_event (monitor, ievent->wd);
         }
 }
 
@@ -460,7 +516,7 @@ inotify_data_pending (GIOChannel    *sou
                 watch = g_hash_table_lookup (monitor->priv->wd_to_watch,
                                              GINT_TO_POINTER (ievent->wd));
                 if (watch != NULL) {
-                        handle_inotify_event (monitor, watch, ievent);
+                        handle_inotify_event (monitor, ievent);
                 }
 
                 i += sizeof (struct inotify_event) + ievent->len;
@@ -523,12 +579,14 @@ file_monitor_remove_notify (CkFileMonito
         g_hash_table_steal (monitor->priv->notifies,
                             GUINT_TO_POINTER (id));
 
-        notify->watch->notifies = g_slist_remove (notify->watch->notifies, GUINT_TO_POINTER (id));
+	if (notify->watch) {
+		notify->watch->notifies = g_slist_remove (notify->watch->notifies, GUINT_TO_POINTER (id));
 
-        if (g_slist_length (notify->watch->notifies) == 0) {
-                file_monitor_remove_watch (monitor, notify->watch);
-                g_free (notify->watch);
-        }
+		if (g_slist_length (notify->watch->notifies) == 0) {
+			file_monitor_remove_watch (monitor, notify->watch);
+			g_free (notify->watch);
+		}
+	}
 
         g_free (notify);
 }
@@ -629,6 +687,7 @@ ck_file_monitor_init (CkFileMonitor *mon
 
         monitor->priv->serial = 1;
         monitor->priv->notify_events = g_queue_new ();
+	monitor->priv->remove_events = g_queue_new ();
 
         setup_inotify (monitor);
 }
@@ -649,6 +708,7 @@ ck_file_monitor_finalize (GObject *objec
 
         g_hash_table_destroy (monitor->priv->notifies);
         g_queue_free (monitor->priv->notify_events);
+	g_queue_free (monitor->priv->remove_events);
 
         G_OBJECT_CLASS (ck_file_monitor_parent_class)->finalize (object);
 }
