1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-02-26 05:57:45 +03:00

src: ensure GSource background unref happens in correct event loop

The g_idle_add function adds a callback to the primary GMainContext.

To workaround the GSource unref bugs, we need to add our callbacks
to the GMainContext that is associated with the GSource being
unref'd. Thus code using the per-VM virEventThread must use its
private GMainContext.

Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2021-03-16 16:26:06 +00:00
parent 78bcf5546b
commit 695bdb3841
9 changed files with 28 additions and 41 deletions

View File

@ -1049,9 +1049,6 @@ if host_machine.system() == 'windows'
else
gio_dep = dependency('gio-unix-2.0', version: '>=' + glib_version)
endif
# GLib event loop race workaround in glibcompat.h, remove when minimum required
# glib is >= 2.64.0
glib_crash_workaround = glib_dep.version().version_compare('<2.64.0')
glib_dep = declare_dependency(
dependencies: [ glib_dep, gobject_dep, gio_dep ],
)

View File

@ -1,11 +0,0 @@
#
# Private symbols specific for pre-2.64.0 GLib workaround
#
# util/glibcompat.h
virEventGLibSourceUnrefIdle;
# Let emacs know we want case-insensitive sorting
# Local Variables:
# sort-fold-case: t
# End:

View File

@ -1733,6 +1733,7 @@ virStorageSourceUpdatePhysicalSize;
# util/glibcompat.h
vir_g_canonicalize_filename;
vir_g_fsync;
vir_g_source_unref;
vir_g_strdup_printf;
vir_g_strdup_vprintf;

View File

@ -124,13 +124,6 @@ else
sym_files += 'libvirt_libssh2.syms'
endif
if glib_crash_workaround
used_sym_files += 'libvirt_glib_crash_workaround.syms'
else
sym_files += 'libvirt_glib_crash_workaround.syms'
endif
# variables filled by subdirectories
libvirt_libs = []

View File

@ -533,7 +533,7 @@ qemuAgentUnregister(qemuAgentPtr agent)
{
if (agent->watch) {
g_source_destroy(agent->watch);
g_vir_source_unref_safe(agent->watch);
vir_g_source_unref(agent->watch, agent->context);
agent->watch = NULL;
}
}

View File

@ -862,7 +862,7 @@ qemuMonitorUnregister(qemuMonitorPtr mon)
{
if (mon->watch) {
g_source_destroy(mon->watch);
g_vir_source_unref_safe(mon->watch);
vir_g_source_unref(mon->watch, mon->context);
mon->watch = NULL;
}
}

View File

@ -231,9 +231,14 @@ vir_g_strdup_vprintf(const char *msg, va_list args)
*
* Drop when min glib >= 2.64.0
*/
#if GLIB_CHECK_VERSION(2, 64, 0) != TRUE
#if GLIB_CHECK_VERSION(2, 64, 0)
void vir_g_source_unref(GSource *src, GMainContext *ctx G_GNUC_UNUSED)
{
g_source_unref(src);
}
#else
gboolean
static gboolean
virEventGLibSourceUnrefIdle(gpointer data)
{
GSource *src = data;
@ -243,4 +248,15 @@ virEventGLibSourceUnrefIdle(gpointer data)
return FALSE;
}
void vir_g_source_unref(GSource *src, GMainContext *ctx)
{
GSource *idle = g_idle_source_new();
g_source_set_callback(idle, virEventGLibSourceUnrefIdle, src, NULL);
g_source_attach(idle, ctx);
g_source_unref(idle);
}
#endif

View File

@ -85,13 +85,4 @@ char *vir_g_strdup_vprintf(const char *msg, va_list args)
#undef g_fsync
#define g_fsync vir_g_fsync
/* Drop when min glib >= 2.64.0 */
#if GLIB_CHECK_VERSION(2, 64, 0)
# define g_vir_source_unref_safe(source) g_source_unref(source)
#else
# define g_vir_source_unref_safe(source) g_idle_add(virEventGLibSourceUnrefIdle, source)
gboolean
virEventGLibSourceUnrefIdle(gpointer data);
#endif
void vir_g_source_unref(GSource *src, GMainContext *ctx);

View File

@ -214,7 +214,7 @@ virEventGLibHandleUpdate(int watch,
if (data->source != NULL) {
VIR_DEBUG("Removed old handle source=%p", data->source);
g_source_destroy(data->source);
g_vir_source_unref_safe(data->source);
vir_g_source_unref(data->source, NULL);
}
data->source = virEventGLibAddSocketWatch(
@ -228,7 +228,7 @@ virEventGLibHandleUpdate(int watch,
VIR_DEBUG("Removed old handle source=%p", data->source);
g_source_destroy(data->source);
g_vir_source_unref_safe(data->source);
vir_g_source_unref(data->source, NULL);
data->source = NULL;
data->events = 0;
}
@ -277,7 +277,7 @@ virEventGLibHandleRemove(int watch)
if (data->source != NULL) {
g_source_destroy(data->source);
g_vir_source_unref_safe(data->source);
vir_g_source_unref(data->source, NULL);
data->source = NULL;
data->events = 0;
}
@ -410,7 +410,7 @@ virEventGLibTimeoutUpdate(int timer,
if (interval >= 0) {
if (data->source != NULL) {
g_source_destroy(data->source);
g_vir_source_unref_safe(data->source);
vir_g_source_unref(data->source, NULL);
}
data->interval = interval;
@ -420,7 +420,7 @@ virEventGLibTimeoutUpdate(int timer,
goto cleanup;
g_source_destroy(data->source);
g_vir_source_unref_safe(data->source);
vir_g_source_unref(data->source, NULL);
data->source = NULL;
}
@ -469,7 +469,7 @@ virEventGLibTimeoutRemove(int timer)
if (data->source != NULL) {
g_source_destroy(data->source);
g_vir_source_unref_safe(data->source);
vir_g_source_unref(data->source, NULL);
data->source = NULL;
}