Otherwise, it will crash next time it goes find(). ==9856== Invalid read of size 4 ==9856== at 0x84E4888: gvir_event_timeout_find (libvirt-glib-event.c:293) ==9856== by 0x84E48E4: gvir_event_timeout_update (libvirt-glib-event.c:308) ==9856== by 0x31AB04BBDB: virEventUpdateTimeout (event.c:122) ==9856== by 0x31AB148758: virNetClientStreamEventTimerUpdate (virnetclientstream.c:81) ==9856== by 0x31AB14991C: virNetClientStreamEventAddCallback (virnetclientstream.c:471) ==9856== by 0x31AB12944F: remoteStreamEventAddCallback (remote_driver.c:3484) ==9856== by 0x31AB108EAC: virStreamEventAddCallback (libvirt.c:14036) ... ==9856== Address 0x143be760 is 0 bytes inside a block of size 40 free'd ==9856== at 0x4A06928: free (vg_replace_malloc.c:427) ==9856== by 0x84E4AD6: gvir_event_timeout_remove (libvirt-glib-event.c:361) ==9856== by 0x31AB04BC2C: virEventRemoveTimeout (event.c:136) ==9856== by 0x31AB149B24: virNetClientStreamEventRemoveCallback (virnetclientstream.c:521) ==9856== by 0x31AB129566: remoteStreamEventRemoveCallback (remote_driver.c:3525) ==9856== by 0x31AB10918F: virStreamEventRemoveCallback (libvirt.c:14114) ... --- libvirt-glib/libvirt-glib-event.c | 83 +++++++++++++++++++++++------------- 1 files changed, 53 insertions(+), 30 deletions(-) diff --git a/libvirt-glib/libvirt-glib-event.c b/libvirt-glib/libvirt-glib-event.c index 8b1bddf..303bec7 100644 --- a/libvirt-glib/libvirt-glib-event.c +++ b/libvirt-glib/libvirt-glib-event.c @@ -61,12 +61,10 @@ struct gvir_event_timeout GMutex *eventlock = NULL; static int nextwatch = 1; -static unsigned int nhandles = 0; -static struct gvir_event_handle **handles = NULL; +static GPtrArray *handles; static int nexttimer = 1; -static unsigned int ntimeouts = 0; -static struct gvir_event_timeout **timeouts = NULL; +static GPtrArray *timeouts; static gboolean gvir_event_handle_dispatch(GIOChannel *source G_GNUC_UNUSED, @@ -106,9 +104,7 @@ gvir_event_handle_add(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 gvir_event_handle, 1); if (events & VIR_EVENT_HANDLE_READABLE) cond |= G_IO_IN; @@ -130,7 +126,7 @@ gvir_event_handle_add(int fd, gvir_event_handle_dispatch, data); - handles[nhandles++] = data; + g_ptr_array_add(handles, data); ret = data->watch; @@ -140,12 +136,24 @@ gvir_event_handle_add(int fd, } static struct gvir_event_handle * -gvir_event_handle_find(int watch) +gvir_event_handle_find(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 gvir_event_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; } @@ -158,7 +166,7 @@ gvir_event_handle_update(int watch, g_mutex_lock(eventlock); - data = gvir_event_handle_find(watch); + data = gvir_event_handle_find(watch, NULL); if (!data) { DEBUG("Update for missing handle watch %d", watch); goto cleanup; @@ -202,7 +210,8 @@ _handle_remove(gpointer data) if (h->ff) (h->ff)(h->opaque); - free(h); + + g_ptr_array_remove_fast(handles, h); return FALSE; } @@ -212,10 +221,11 @@ gvir_event_handle_remove(int watch) { struct gvir_event_handle *data; int ret = -1; + guint idx; g_mutex_lock(eventlock); - data = gvir_event_handle_find(watch); + data = gvir_event_handle_find(watch, &idx); if (!data) { DEBUG("Remove of missing watch %d", watch); goto cleanup; @@ -259,10 +269,7 @@ gvir_event_timeout_add(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 gvir_event_timeout, 1); data->timer = nexttimer++; data->interval = interval; data->cb = cb; @@ -273,7 +280,7 @@ gvir_event_timeout_add(int interval, gvir_event_timeout_dispatch, data); - timeouts[ntimeouts++] = data; + g_ptr_array_add(timeouts, data); DEBUG("Add timeout %p %d %p %p %d\n", data, interval, cb, opaque, data->timer); @@ -286,12 +293,26 @@ gvir_event_timeout_add(int interval, static struct gvir_event_timeout * -gvir_event_timeout_find(int timer) +gvir_event_timeout_find(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 gvir_event_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; } @@ -305,7 +326,7 @@ gvir_event_timeout_update(int timer, g_mutex_lock(eventlock); - data = gvir_event_timeout_find(timer); + data = gvir_event_timeout_find(timer, NULL); if (!data) { DEBUG("Update of missing timer %d", timer); goto cleanup; @@ -337,11 +358,12 @@ static int gvir_event_timeout_remove(int timer) { struct gvir_event_timeout *data; + guint idx; int ret = -1; g_mutex_lock(eventlock); - data = gvir_event_timeout_find(timer); + data = gvir_event_timeout_find(timer, &idx); if (!data) { DEBUG("Remove of missing timer %d", timer); goto cleanup; @@ -358,8 +380,7 @@ gvir_event_timeout_remove(int timer) if (data->ff) (data->ff)(data->opaque); - free(data); - + g_ptr_array_remove_index_fast(timeouts, idx); ret = 0; cleanup: @@ -371,6 +392,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(gvir_event_handle_add, gvir_event_handle_update, gvir_event_handle_remove, -- 1.7.6.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list