[virt-tools-list] [virt-viewer v2 03/13] events: remove timeout and handle from arrays

Fabiano Fidêncio fidencio at redhat.com
Wed Jul 22 08:04:30 UTC 2015


Otherwise, it will crash next time it goes find()

Backtrace:
(gdb) where
 #0  0x00007efcae715095 in g_io_create_watch () from
 /lib64/libglib-2.0.so.0
 #1  0x00007efcae7150ef in g_io_add_watch_full () from
 /lib64/libglib-2.0.so.0
 #2  0x00000000004275ba in virt_viewer_events_update_handle
 (watch=<optimized out>, events=1) at
 virt-viewer-events.c:158
 #3  0x00007efcb1a62dce in virNetSocketUpdateIOCallback (sock=0x1e75c00,
 events=1) at rpc/virnetsocket.c:1981
 #4  0x00007efcb1a50113 in virNetClientIOUpdateCallback
 (client=<optimized out>, enableCallback=<optimized out>) at
 rpc/virnetclient.c:1639
 #5  0x00007efcb1a50f82 in virNetClientIO (thiscall=0x20e0170,
 client=0x1f2e060) at rpc/virnetclient.c:1793
 #6  virNetClientSendInternal (client=client at entry=0x1f2e060,
 msg=msg at entry=0x20e0100,
 expectReply=expectReply at entry=false, nonBlock=nonBlock at entry=true) at
 rpc/virnetclient.c:1962
 #7  0x00007efcb1a52413 in virNetClientSendNonBlock (client=0x1f2e060,
 msg=msg at entry=0x20e0100) at
 rpc/virnetclient.c:2036
 #8  0x00007efcb1a5243d in virNetClientKeepAliveSendCB (opaque=<optimized
 out>, msg=0x20e0100) at
 rpc/virnetclient.c:293
 #9  0x00007efcb1a5ba02 in virKeepAliveTimer (timer=<optimized out>,
 opaque=0x20d3d00) at rpc/virkeepalive.c:176
 #10 0x00000000004272e9 in virt_viewer_events_dispatch_timeout
 (opaque=0x1e6cd30) at virt-viewer-events.c:233
 #11 0x00007efcae7231b3 in g_timeout_dispatch () from
 /lib64/libglib-2.0.so.0
 #12 0x00007efcae72279a in g_main_context_dispatch () from
 /lib64/libglib-2.0.so.0
 #13 0x00007efcae722ae8 in g_main_context_iterate.isra.24 () from
 /lib64/libglib-2.0.so.0
 #14 0x00007efcae722dba in g_main_loop_run () from
 /lib64/libglib-2.0.so.0
 #15 0x00007efcb054a045 in gtk_main () from /lib64/libgtk-3.so.0
 #16 0x0000000000410a9c in main (argc=1, argv=0x7ffde58a7978) at
 virt-viewer-main.c:124

Based on commit cff5f1c46f4b9661e112b85159fb58ae473a9a89 from
libvirt-glib.
Original author: Marc-André Lureau <marcandre.lureau at redhat.com>

Related to: rhbz#1243228
---
 src/virt-viewer-events.c | 80 +++++++++++++++++++++++++++++++-----------------
 1 file changed, 52 insertions(+), 28 deletions(-)

diff --git a/src/virt-viewer-events.c b/src/virt-viewer-events.c
index 5e438b8..02b7216 100644
--- a/src/virt-viewer-events.c
+++ b/src/virt-viewer-events.c
@@ -51,8 +51,7 @@ struct virt_viewer_events_handle
 };
 
 static int nextwatch = 1;
-static unsigned int nhandles = 0;
-static struct virt_viewer_events_handle **handles = NULL;
+static GPtrArray *handles;
 
 static gboolean
 virt_viewer_events_dispatch_handle(GIOChannel *source G_GNUC_UNUSED,
@@ -92,9 +91,7 @@ int virt_viewer_events_add_handle(int fd,
 
     g_mutex_lock(eventlock);
 
-    handles = g_realloc(handles, sizeof(*handles)*(nhandles+1));
-    data = g_malloc(sizeof(*data));
-    memset(data, 0, sizeof(*data));
+    data = g_new0(struct virt_viewer_events_handle, 1);
 
     if (events & VIR_EVENT_HANDLE_READABLE)
         cond |= G_IO_IN;
@@ -121,7 +118,7 @@ int virt_viewer_events_add_handle(int fd,
                                   virt_viewer_events_dispatch_handle,
                                   data);
 
-    handles[nhandles++] = data;
+    g_ptr_array_add(handles, data);
 
     ret = data->watch;
 
@@ -131,12 +128,24 @@ int virt_viewer_events_add_handle(int fd,
 }
 
 static struct virt_viewer_events_handle *
-virt_viewer_events_find_handle(int watch)
+virt_viewer_events_find_handle(int watch, guint *idx)
 {
-    unsigned int i;
-    for (i = 0 ; i < nhandles ; i++)
-        if (handles[i]->watch == watch)
-            return handles[i];
+    guint i;
+
+    for (i = 0 ; i < handles->len ; i++) {
+        struct virt_viewer_events_handle *h = g_ptr_array_index(handles, i);
+
+        if (h == NULL) {
+            g_warn_if_reached ();
+            continue;
+        }
+
+        if (h->watch == watch) {
+            if (idx != NULL)
+                *idx = i;
+            return h;
+        }
+    }
 
     return NULL;
 }
@@ -149,7 +158,7 @@ virt_viewer_events_update_handle(int watch,
 
     g_mutex_lock(eventlock);
 
-    data = virt_viewer_events_find_handle(watch);
+    data = virt_viewer_events_find_handle(watch, NULL);
 
     if (!data) {
         g_debug("Update for missing handle watch %d", watch);
@@ -199,7 +208,7 @@ virt_viewer_events_cleanup_handle(gpointer user_data)
     if (data->ff)
         (data->ff)(data->opaque);
 
-    free(data);
+    g_ptr_array_remove_fast(handles, data);
     return FALSE;
 }
 
@@ -209,10 +218,11 @@ virt_viewer_events_remove_handle(int watch)
 {
     struct virt_viewer_events_handle *data;
     int ret = -1;
+    guint idx;
 
     g_mutex_lock(eventlock);
 
-    data = virt_viewer_events_find_handle(watch);
+    data = virt_viewer_events_find_handle(watch, &idx);
 
     if (!data) {
         g_debug("Remove of missing watch %d", watch);
@@ -248,8 +258,7 @@ struct virt_viewer_events_timeout
 
 
 static int nexttimer = 1;
-static unsigned int ntimeouts = 0;
-static struct virt_viewer_events_timeout **timeouts = NULL;
+static GPtrArray *timeouts;
 
 static gboolean
 virt_viewer_events_dispatch_timeout(void *opaque)
@@ -272,9 +281,7 @@ virt_viewer_events_add_timeout(int interval,
 
     g_mutex_lock(eventlock);
 
-    timeouts = g_realloc(timeouts, sizeof(*timeouts)*(ntimeouts+1));
-    data = g_malloc(sizeof(*data));
-    memset(data, 0, sizeof(*data));
+    data = g_new0(struct virt_viewer_events_timeout, 1);
 
     data->timer = nexttimer++;
     data->interval = interval;
@@ -286,7 +293,7 @@ virt_viewer_events_add_timeout(int interval,
                                      virt_viewer_events_dispatch_timeout,
                                      data);
 
-    timeouts[ntimeouts++] = data;
+    g_ptr_array_add(timeouts, data);
 
     g_debug("Add timeout %p %d %p %p %d", data, interval, cb, opaque, data->timer);
 
@@ -299,12 +306,26 @@ virt_viewer_events_add_timeout(int interval,
 
 
 static struct virt_viewer_events_timeout *
-virt_viewer_events_find_timeout(int timer)
+virt_viewer_events_find_timeout(int timer, guint *idx)
 {
-    unsigned int i;
-    for (i = 0 ; i < ntimeouts ; i++)
-        if (timeouts[i]->timer == timer)
-            return timeouts[i];
+    guint i;
+
+    g_return_val_if_fail(timeouts != NULL, NULL);
+
+    for (i = 0 ; i < timeouts->len ; i++) {
+        struct virt_viewer_events_timeout *t = g_ptr_array_index(timeouts, i);
+
+        if (t == NULL) {
+            g_warn_if_reached ();
+            continue;
+        }
+
+        if (t->timer == timer) {
+            if (idx != NULL)
+                *idx = i;
+            return t;
+        }
+    }
 
     return NULL;
 }
@@ -318,7 +339,7 @@ virt_viewer_events_update_timeout(int timer,
 
     g_mutex_lock(eventlock);
 
-    data = virt_viewer_events_find_timeout(timer);
+    data = virt_viewer_events_find_timeout(timer, NULL);
     if (!data) {
         g_debug("Update of missing timer %d", timer);
         goto cleanup;
@@ -358,7 +379,7 @@ virt_viewer_events_cleanup_timeout(gpointer user_data)
     if (data->ff)
         (data->ff)(data->opaque);
 
-    free(data);
+    g_ptr_array_remove_fast(timeouts, data);
     return FALSE;
 }
 
@@ -368,10 +389,11 @@ virt_viewer_events_remove_timeout(int timer)
 {
     struct virt_viewer_events_timeout *data;
     int ret = -1;
+    guint idx;
 
     g_mutex_lock(eventlock);
 
-    data = virt_viewer_events_find_timeout(timer);
+    data = virt_viewer_events_find_timeout(timer, &idx);
     if (!data) {
         g_debug("Remove of missing timer %d", timer);
         goto cleanup;
@@ -396,6 +418,8 @@ cleanup:
 static gpointer event_register_once(gpointer data G_GNUC_UNUSED)
 {
     eventlock = g_mutex_new();
+    timeouts = g_ptr_array_new_with_free_func(g_free);
+    handles = g_ptr_array_new_with_free_func(g_free);
     virEventRegisterImpl(virt_viewer_events_add_handle,
                          virt_viewer_events_update_handle,
                          virt_viewer_events_remove_handle,
-- 
2.4.4




More information about the virt-tools-list mailing list