[gjs] dbus: increase refcount on all signal handler candidates before iterating



commit 2bf52e4325560e47cc2f0dd14621c7cb3a8fe94d
Author: Tommi Komulainen <tko litl com>
Date:   Thu May 14 17:40:46 2009 +0100

    dbus: increase refcount on all signal handler candidates before iterating
    
    Calling a watcher handler might result in another watcher still in the
    list becoming unref'd and destroyed but still dangling in the candidates
    list. Increasing the refcount of all candidates keeps them alive until
    handled.
    
    Invalid read of size 4
       at 0x41CEEC3: _big_dbus_signal_watch_filter_message (dbus-signals.c:530)
       by 0x4C01A36: dbus_connection_dispatch (in /usr/lib/libdbus-1.so.3.4.0)
       by 0x508E59C: (within /usr/lib/libdbus-glib-1.so.2.1.0)
       by 0x4A59CF5: g_main_context_dispatch (in /usr/lib/libglib-2.0.so.0.1600.6)
       by 0x4A5D0B2: (within /usr/lib/libglib-2.0.so.0.1600.6)
       by 0x4A5D496: g_main_loop_run (in /usr/lib/libglib-2.0.so.0.1600.6)
       by 0x80489B7: main (main.c:82)
     Address 0x60cc874 is 12 bytes inside a block of size 44 free'd
       at 0x402265C: free (vg_replace_malloc.c:323)
       by 0x4A61B80: g_free (in /usr/lib/libglib-2.0.so.0.1600.6)
       by 0x41CE5E3: signal_watcher_unref (dbus-signals.c:95)
       by 0x41CE91E: big_dbus_unwatch_signal_by_id (dbus-signals.c:872)
       by 0x5B1EC92: big_js_dbus_unwatch_signal_by_id (dbus.c:707)
       by 0x4B4F37F: js_Invoke (jsinterp.c:1304)
       by 0x4B4222B: js_Interpret (jsinterp.c:4877)
       by 0x4B4F3CE: js_Invoke (jsinterp.c:1320)
       by 0x4B3D519: fun_apply (jsfun.c:1678)
       by 0x4B442AC: js_Interpret (jsinterp.c:4860)
       by 0x4B4F3CE: js_Invoke (jsinterp.c:1320)
       by 0x4B3D519: fun_apply (jsfun.c:1678)
---
 gjsdbus/dbus-signals.c |   13 ++++++++-----
 1 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/gjsdbus/dbus-signals.c b/gjsdbus/dbus-signals.c
index bdb58bc..9910463 100644
--- a/gjsdbus/dbus-signals.c
+++ b/gjsdbus/dbus-signals.c
@@ -636,6 +636,10 @@ _gjs_dbus_signal_watch_filter_message(DBusConnection *connection,
     /* Sort so we can find dups */
     candidates = g_slist_sort(candidates, direct_cmp);
 
+    /* Ref everything so that calling a handler doesn't unref another
+     * and possibly leave it dangling in our candidates list */
+    g_slist_foreach(candidates, (GFunc)signal_watcher_ref, NULL);
+
     previous = NULL;
     while (candidates != NULL) {
         GjsSignalWatcher *watcher;
@@ -644,29 +648,28 @@ _gjs_dbus_signal_watch_filter_message(DBusConnection *connection,
         candidates = g_slist_delete_link(candidates, candidates);
 
         if (previous == watcher)
-            continue; /* watcher was in more than one table */
+            goto end_while; /* watcher was in more than one table */
 
         previous = watcher;
 
         if (!signal_watcher_watches(info,
                                     watcher,
                                     sender, path, iface, name))
-            continue;
+            goto end_while;
 
         /* destroyed would happen if e.g. removed while we are going
          * through here.
          */
         if (watcher->destroyed)
-            continue;
+            goto end_while;
 
         /* Invoke the watcher */
 
-        signal_watcher_ref(watcher);
-
         (* watcher->handler) (connection,
                               message,
                               watcher->data);
 
+    end_while:
         signal_watcher_unref(watcher);
     }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]