mirror of
https://gitlab.com/virt-viewer/virt-viewer.git
synced 2025-01-10 01:17:47 +03:00
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
This commit is contained in:
parent
3cbb6232f3
commit
8a2420ecdf
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user