diff --git a/gio/glocalfilemonitor.c b/gio/glocalfilemonitor.c index f408d0707..68afd7b51 100644 --- a/gio/glocalfilemonitor.c +++ b/gio/glocalfilemonitor.c @@ -358,11 +358,28 @@ g_file_monitor_source_handle_event (GFileMonitorSource *fms, g_mutex_lock (&fms->lock); - /* NOTE: We process events even if the file monitor has already been disposed. - * The reason is that we must not take a reference to the instance here - * as destroying it from the event handling thread will lead to a - * deadlock when taking the lock in _ih_sub_cancel. + /* NOTE: + * + * We process events even if the file monitor has already been disposed. + * The reason is that we must not take a reference to the instance here as + * destroying it from the event handling thread will lead to a deadlock when + * taking the lock in _ih_sub_cancel. + * + * This results in seemingly-unbounded growth of the `event_queue` with the + * calls to `g_file_monitor_source_queue_event()`. However, each of those sets + * the ready time on the #GSource, which means that it will be dispatched in + * a subsequent iteration of the #GMainContext it’s attached to. At that + * point, `g_file_monitor_source_dispatch()` will return %FALSE, and this will + * trigger finalisation of the source. That will clear the `event_queue`. + * + * If the source is no longer attached, this will return early to prevent + * unbounded queueing. */ + if (g_source_is_destroyed ((GSource *) fms)) + { + g_mutex_unlock (&fms->lock); + return TRUE; + } switch (event_type) { @@ -595,9 +612,9 @@ g_file_monitor_source_dispose (GFileMonitorSource *fms) g_file_monitor_source_update_ready_time (fms); - g_mutex_unlock (&fms->lock); - g_source_destroy ((GSource *) fms); + + g_mutex_unlock (&fms->lock); } static void