summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabiano FidĂȘncio <fidencio@redhat.com>2015-07-22 02:48:05 +0200
committerFabiano FidĂȘncio <fidencio@redhat.com>2015-07-22 14:56:57 +0200
commit8a2420ecdfe7ae9eff3f7c9a0c0412af7d985fab (patch)
tree7c0c5b9418b61a72a4b8ddaaa1ed4aba854f06c9
parent3cbb6232f33d0ecdc7f58e2ea8eb7830f9fe007f (diff)
downloadvirt-viewer-8a2420ecdfe7ae9eff3f7c9a0c0412af7d985fab.tar.gz
virt-viewer-8a2420ecdfe7ae9eff3f7c9a0c0412af7d985fab.tar.xz
virt-viewer-8a2420ecdfe7ae9eff3f7c9a0c0412af7d985fab.zip
events: ensure event callbacks are threadsafe
Take a global lock whenever changing any event callbacks to ensure thread safety. Based on commit f1fe67da2dac6a249f796535b8dbd155d5741ad7 from libvirt-glib. Original author: Daniel P. Berrange <berrange@redhat.com> Related to: rhbz#1243228
-rw-r--r--src/virt-viewer-events.c83
1 files changed, 65 insertions, 18 deletions
diff --git a/src/virt-viewer-events.c b/src/virt-viewer-events.c
index 3b5a136..f767c2e 100644
--- a/src/virt-viewer-events.c
+++ b/src/virt-viewer-events.c
@@ -34,6 +34,8 @@
#include "virt-viewer-events.h"
+static GMutex *eventlock = NULL;
+
struct virt_viewer_events_handle
{
int watch;
@@ -85,6 +87,9 @@ int virt_viewer_events_add_handle(int fd,
{
struct virt_viewer_events_handle *data;
GIOCondition cond = 0;
+ int ret;
+
+ g_mutex_lock(eventlock);
handles = g_realloc(handles, sizeof(*handles)*(nhandles+1));
data = g_malloc(sizeof(*data));
@@ -117,7 +122,11 @@ int virt_viewer_events_add_handle(int fd,
handles[nhandles++] = data;
- return data->watch;
+ ret = data->watch;
+
+ g_mutex_unlock(eventlock);
+
+ return ret;
}
static struct virt_viewer_events_handle *
@@ -135,17 +144,21 @@ static void
virt_viewer_events_update_handle(int watch,
int events)
{
- struct virt_viewer_events_handle *data = virt_viewer_events_find_handle(watch);
+ struct virt_viewer_events_handle *data;
+
+ g_mutex_lock(eventlock);
+
+ data = virt_viewer_events_find_handle(watch);
if (!data) {
g_debug("Update for missing handle watch %d", watch);
- return;
+ goto cleanup;
}
if (events) {
GIOCondition cond = 0;
if (events == data->events)
- return;
+ goto cleanup;
if (data->source)
g_source_remove(data->source);
@@ -162,12 +175,15 @@ virt_viewer_events_update_handle(int watch,
data->events = events;
} else {
if (!data->source)
- return;
+ goto cleanup;
g_source_remove(data->source);
data->source = 0;
data->events = 0;
}
+
+cleanup:
+ g_mutex_unlock(eventlock);
}
@@ -190,24 +206,33 @@ virt_viewer_events_cleanup_handle(gpointer user_data)
static int
virt_viewer_events_remove_handle(int watch)
{
- struct virt_viewer_events_handle *data = virt_viewer_events_find_handle(watch);
+ struct virt_viewer_events_handle *data;
+ int ret = -1;
+
+ g_mutex_lock(eventlock);
+
+ data = virt_viewer_events_find_handle(watch);
if (!data) {
g_debug("Remove of missing watch %d", watch);
- return -1;
+ goto cleanup;
}
g_debug("Remove handle %d %d", watch, data->fd);
if (!data->source)
- return -1;
+ goto cleanup;
g_source_remove(data->source);
data->source = 0;
data->events = 0;
g_idle_add(virt_viewer_events_cleanup_handle, data);
- return 0;
+ ret = 0;
+
+cleanup:
+ g_mutex_unlock(eventlock);
+ return ret;
}
struct virt_viewer_events_timeout
@@ -242,6 +267,9 @@ virt_viewer_events_add_timeout(int interval,
virFreeCallback ff)
{
struct virt_viewer_events_timeout *data;
+ int ret;
+
+ g_mutex_lock(eventlock);
timeouts = g_realloc(timeouts, sizeof(*timeouts)*(ntimeouts+1));
data = g_malloc(sizeof(*data));
@@ -261,7 +289,11 @@ virt_viewer_events_add_timeout(int interval,
g_debug("Add timeout %p %d %p %p %d", data, interval, cb, opaque, data->timer);
- return data->timer;
+ ret = data->timer;
+
+ g_mutex_unlock(eventlock);
+
+ return ret;
}
@@ -281,18 +313,21 @@ static void
virt_viewer_events_update_timeout(int timer,
int interval)
{
- struct virt_viewer_events_timeout *data = virt_viewer_events_find_timeout(timer);
+ struct virt_viewer_events_timeout *data;
+ g_mutex_lock(eventlock);
+
+ data = virt_viewer_events_find_timeout(timer);
if (!data) {
g_debug("Update of missing timer %d", timer);
- return;
+ goto cleanup;
}
g_debug("Update timeout %p %d %d", data, timer, interval);
if (interval >= 0) {
if (data->source)
- return;
+ goto cleanup;
data->interval = interval;
data->source = g_timeout_add(data->interval,
@@ -300,11 +335,14 @@ virt_viewer_events_update_timeout(int timer,
data);
} else {
if (!data->source)
- return;
+ goto cleanup;
g_source_remove(data->source);
data->source = 0;
}
+
+cleanup:
+ g_mutex_unlock(eventlock);
}
@@ -327,27 +365,36 @@ virt_viewer_events_cleanup_timeout(gpointer user_data)
static int
virt_viewer_events_remove_timeout(int timer)
{
- struct virt_viewer_events_timeout *data = virt_viewer_events_find_timeout(timer);
+ struct virt_viewer_events_timeout *data;
+ int ret = -1;
+ g_mutex_lock(eventlock);
+
+ data = virt_viewer_events_find_timeout(timer);
if (!data) {
g_debug("Remove of missing timer %d", timer);
- return -1;
+ goto cleanup;
}
g_debug("Remove timeout %p %d", data, timer);
if (!data->source)
- return -1;
+ goto cleanup;
g_source_remove(data->source);
data->source = 0;
g_idle_add(virt_viewer_events_cleanup_timeout, data);
- return 0;
+ ret = 0;
+
+cleanup:
+ g_mutex_unlock(eventlock);
+ return ret;
}
void virt_viewer_events_register(void) {
+ eventlock = g_mutex_new();
virEventRegisterImpl(virt_viewer_events_add_handle,
virt_viewer_events_update_handle,
virt_viewer_events_remove_handle,