Hi,

Use glib g_object_ref/unref to avoid accessing destroyed logs in g_timeout_add.

$ svn diff
Index: patches/gnome-utils-04-logview-plugin.diff
===================================================================
--- patches/gnome-utils-04-logview-plugin.diff  (revision 10425)
+++ patches/gnome-utils-04-logview-plugin.diff  (working copy)
@@ -7976,11 +7976,11 @@
 +
 +#endif /* __LOGVIEW_IFACE_H__ */
 +
-Index: gnome-utils-trunk/logview/monitor.c
+Index: gnome-utils/logview/monitor.c
 ===================================================================
---- gnome-utils-trunk/logview/monitor.c        (revision 7356)
-+++ gnome-utils-trunk/logview/monitor.c        (working copy)
-@@ -1,98 +1,159 @@
+--- gnome-utils/logview/monitor.c      (revision 7378)
++++ gnome-utils/logview/monitor.c      (working copy)
+@@ -1,98 +1,156 @@
 -/*  ----------------------------------------------------------------------
 +/*    ----------------------------------------------------------------------
  
@@ -8028,7 +8028,6 @@
 +#include "logview-debug.h"
  
 +#define CHECK_FILE_PERIOD     10000
-+static GSList *monitor_list = NULL;
 +
  void
  monitor_stop (Log *log)
@@ -8036,7 +8035,7 @@
 -  g_return_if_fail (log);
 +      GnomeVFSMonitorHandle *mon_handle;
 +      LV_MARK;
-+      g_return_if_fail (log);
++      g_assert (LOGVIEW_IS_LOG (log));
  
 -  if (log->mon_handle != NULL) {
 -      gnome_vfs_monitor_cancel (log->mon_handle);
@@ -8048,18 +8047,16 @@
 -      
 -      log->monitored = FALSE;
 -  }
-+      if (g_slist_find (monitor_list, log)) {
-+              monitor_list = g_slist_remove (monitor_list, log);
-+              g_object_get (G_OBJECT (log),
-+                            "monitor-handle", &mon_handle, NULL);
-+              if (mon_handle != NULL) {
-+                      gnome_vfs_monitor_cancel (mon_handle);
-+                      g_object_set (G_OBJECT (log),
-+                                    "monitor-handle", NULL, NULL);
-+              }
++      g_object_get (G_OBJECT (log),
++                    "monitor-handle", &mon_handle, NULL);
++      if (mon_handle != NULL) {
++              gnome_vfs_monitor_cancel (mon_handle);
 +              g_object_set (G_OBJECT (log),
-+                            "monitoring", FALSE, NULL);
++                            "monitor-handle", NULL, NULL);
 +      }
++      g_object_set (G_OBJECT (log),
++                    "monitoring", FALSE, NULL);
++      g_object_unref (log);
  }
  
  static void
@@ -8077,7 +8074,7 @@
 +      Log *log = data;
 +
 +      LV_MARK;
-+      g_assert (log);
++      g_assert (LOGVIEW_IS_LOG (log));
 +
 +      g_object_get (G_OBJECT (log),
 +                    "window", &logview,
@@ -8095,7 +8092,9 @@
 +/* ----------------------------------------------------------------------
 +NAME: monitor_log_was_modified
 +DESCRIPTION: Returns true if modified flag in log changed. It also
-+changes the modified flag.
++changes the modified flag. This function is called in unexpected time,
++so the passed in log must be referenced. And only unreferenced when timer
++is invalid.
 +---------------------------------------------------------------------- */
 +
 +static gboolean
@@ -8103,12 +8102,12 @@
 +{
 +      gboolean monitoring;
 +      LV_MARK;
-+      if (g_slist_find (monitor_list, log) == NULL )
-+              return FALSE;
-+      g_return_val_if_fail (LOGVIEW_IS_LOG (log), FALSE);
++      g_assert (LOGVIEW_IS_LOG (log));
 +      g_object_get (G_OBJECT (log), "monitoring", &monitoring, NULL);
-+      if (! monitoring)
++      if (! monitoring) {
++              g_object_unref (log);
 +              return FALSE;
++      }
 +      if (log_has_been_modified (log)) {
 +              monitor_callback(NULL, NULL, NULL, 0, log);
 +      }
@@ -8135,8 +8134,9 @@
 -  result = gnome_vfs_tell (log->mon_file_handle, &size);
 -  log->mon_offset = size;
 +      LV_MARK;
-+      g_return_if_fail (log);
++      g_assert (LOGVIEW_IS_LOG (log));
 +
++      g_object_ref (log);
 +      g_object_get (G_OBJECT (log),
 +                    "monitorable", &monitorable,
 +                    "monitor-handle", &mon_handle,
@@ -8144,17 +8144,10 @@
 +                    NULL);
 +      if (!monitorable) {
 +              g_free (name);
++              g_object_unref (log);
 +              return;
 +      }
 +
-+      if (g_slist_find (monitor_list, log)) {
-+              g_free (name);
-+              return;
-+      }
- 
--  result = gnome_vfs_monitor_add (&(log->mon_handle), log->name,
--                         GNOME_VFS_MONITOR_FILE, monitor_callback,
--                         log);
 +      result = gnome_vfs_monitor_add (&mon_handle, name,
 +                                      GNOME_VFS_MONITOR_FILE,
 +                                      monitor_callback, log);
@@ -8162,7 +8155,8 @@
 +              if (result == GNOME_VFS_ERROR_NOT_SUPPORTED) {
 +                      mon_handle = NULL;
 +                      g_timeout_add (CHECK_FILE_PERIOD,
-+                                     (GSourceFunc) monitor_log_was_modified, 
log);
++                                     (GSourceFunc) monitor_log_was_modified,
++                                     g_object_ref(log));
 +              }
 +              else {
 +                      goto gnome_vfs_err;
@@ -8173,6 +8167,14 @@
 +                            "monitor-handle", mon_handle, NULL);
 +      }
  
+-  result = gnome_vfs_monitor_add (&(log->mon_handle), log->name,
+-                         GNOME_VFS_MONITOR_FILE, monitor_callback,
+-                         log);
++      g_object_set (G_OBJECT (log),
++                    "monitoring", TRUE, NULL);
++      g_free (name);
++      return;
+ 
 -  if (result != GNOME_VFS_OK) {
 -    main = g_strdup (_("This file cannot be monitored."));
 -    switch (result) {
@@ -8187,12 +8189,7 @@
 -    gnome_vfs_close (log->mon_file_handle);
 -    return;
 -  }
-+      g_object_set (G_OBJECT (log),
-+                    "monitoring", TRUE, NULL);
-+      monitor_list = g_slist_append (monitor_list, log);
-+      g_free (name);
-+      return;
- 
+-
 -  log->monitored = TRUE;
 +gnome_vfs_err:
 +      first = g_strdup (_("Gnome-VFS error."));
@@ -8204,6 +8201,7 @@
 +      g_free (first);
 +      g_free (second);
 +      g_free (name);
++      g_object_unref (log);
  }


-- 
x82120 / +86 10 82618200


Reply via email to