diff options
author | Fabiano Fidêncio <fidencio@redhat.com> | 2015-07-22 03:16:37 +0200 |
---|---|---|
committer | Fabiano Fidêncio <fidencio@redhat.com> | 2015-07-22 14:56:57 +0200 |
commit | d28077ad08f46514f75ca13d9656635cc2111bd5 (patch) | |
tree | bc7984716edc28088f877cd59a6ebddbe02c3a5d | |
parent | 0a464aae9a764c404ea76fe2212d45e5b2d87d2f (diff) |
events: remove timeout and handle from arrays
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@entry=0x1f2e060,
msg=msg@entry=0x20e0100,
expectReply=expectReply@entry=false, nonBlock=nonBlock@entry=true) at
rpc/virnetclient.c:1962
#7 0x00007efcb1a52413 in virNetClientSendNonBlock (client=0x1f2e060,
msg=msg@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@redhat.com>
Related to: rhbz#1243228
-rw-r--r-- | src/virt-viewer-events.c | 80 |
1 files changed, 52 insertions, 28 deletions
diff --git a/src/virt-viewer-events.c b/src/virt-viewer-events.c index daf128e..74828f5 100644 --- a/src/virt-viewer-events.c +++ b/src/virt-viewer-events.c @@ -50,8 +50,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, @@ -91,9 +90,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; @@ -120,7 +117,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; @@ -130,12 +127,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; } @@ -148,7 +157,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); @@ -198,7 +207,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; } @@ -208,10 +217,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); @@ -247,8 +257,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) @@ -271,9 +280,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; @@ -285,7 +292,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); @@ -298,12 +305,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; } @@ -317,7 +338,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; @@ -357,7 +378,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; } @@ -367,10 +388,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; @@ -395,6 +417,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, |