[virt-tools-list] [virt-viewer][PATCH 2/6] events: remove timeout and handle from arrays

Fabiano Fidêncio fidencio at redhat.com
Fri Jul 17 14:01:19 UTC 2015


Based on
http://libvirt.org/git/?p=libvirt-glib.git;a=commit;h=cff5f1c46f4b9661e112b85159fb58ae473a9a89

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

diff --git a/src/virt-viewer-events.c b/src/virt-viewer-events.c
index 6154353..b92506c 100644
--- a/src/virt-viewer-events.c
+++ b/src/virt-viewer-events.c
@@ -39,7 +39,7 @@ struct virt_viewer_events_handle
     int watch;
     int fd;
     int events;
-    int enabled;
+    int removed;
     GIOChannel *channel;
     guint source;
     virEventHandleCallback cb;
@@ -48,8 +48,7 @@ struct virt_viewer_events_handle
 };
 
 static int nextwatch = 1;
-static unsigned int nhandles = 0;
-static struct virt_viewer_events_handle **handles = NULL;
+GPtrArray *handles;
 
 static gboolean
 virt_viewer_events_dispatch_handle(GIOChannel *source G_GNUC_UNUSED,
@@ -86,9 +85,7 @@ int virt_viewer_events_add_handle(int fd,
     struct virt_viewer_events_handle *data;
     GIOCondition cond = 0;
 
-    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;
@@ -115,7 +112,7 @@ int virt_viewer_events_add_handle(int fd,
                                   virt_viewer_events_dispatch_handle,
                                   data);
 
-    handles[nhandles++] = data;
+    g_ptr_array_add(handles, data);
 
     return data->watch;
 }
@@ -123,10 +120,22 @@ int virt_viewer_events_add_handle(int fd,
 static struct virt_viewer_events_handle *
 virt_viewer_events_find_handle(int watch)
 {
-    unsigned int i;
-    for (i = 0 ; i < nhandles ; i++)
-        if (handles[i]->watch == watch)
-            return handles[i];
+    guint i;
+
+    g_return_val_if_fail(handles != NULL, NULL);
+
+    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) && !h->removed) {
+            return h;
+        }
+    }
 
     return NULL;
 }
@@ -182,7 +191,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;
 }
 
@@ -199,13 +208,17 @@ virt_viewer_events_remove_handle(int watch)
 
     g_debug("Remove handle %d %d", watch, data->fd);
 
-    if (!data->source)
-        return -1;
-
-    g_source_remove(data->source);
-    data->source = 0;
-    data->events = 0;
+    if (data->source) {
+        g_source_remove(data->source);
+        data->source = 0;
+        data->events = 0;
+    }
 
+    /* since the actual watch deletion is done asynchronously, a handle_update call may
+     * reschedule the watch befure it's fully deleted, that's why we need to mar it as
+     * 'removed' to prevent reuse
+     */
+    data->removed = TRUE;
     g_idle_add(virt_viewer_events_cleanup_handle, data);
     return 0;
 }
@@ -214,6 +227,7 @@ struct virt_viewer_events_timeout
 {
     int timer;
     int interval;
+    int removed;
     guint source;
     virEventTimeoutCallback cb;
     void *opaque;
@@ -222,8 +236,7 @@ struct virt_viewer_events_timeout
 
 
 static int nexttimer = 1;
-static unsigned int ntimeouts = 0;
-static struct virt_viewer_events_timeout **timeouts = NULL;
+GPtrArray *timeouts;
 
 static gboolean
 virt_viewer_events_dispatch_timeout(void *opaque)
@@ -243,9 +256,7 @@ virt_viewer_events_add_timeout(int interval,
 {
     struct virt_viewer_events_timeout *data;
 
-    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;
@@ -257,7 +268,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);
 
@@ -268,10 +279,22 @@ virt_viewer_events_add_timeout(int interval,
 static struct virt_viewer_events_timeout *
 virt_viewer_events_find_timeout(int timer)
 {
-    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) && !t->removed) {
+            return t;
+        }
+    }
 
     return NULL;
 }
@@ -319,7 +342,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;
 }
 
@@ -336,18 +359,24 @@ virt_viewer_events_remove_timeout(int timer)
 
     g_debug("Remove timeout %p %d", data, timer);
 
-    if (!data->source)
-        return -1;
-
-    g_source_remove(data->source);
-    data->source = 0;
+    if (data->source) {
+        g_source_remove(data->source);
+        data->source = 0;
+    }
 
+    /* since the actual timeout deletion is done asynchronously, a timeout_update call my
+     * reschedule the timeout before it's fully deleted, that's why we need to mark it as
+     * 'removed' to prevent reuse
+     */
+    data->removed = TRUE;
     g_idle_add(virt_viewer_events_cleanup_timeout, data);
     return 0;
 }
 
 static gpointer event_register_once(gpointer data G_GNUC_UNUSED)
 {
+    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