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:
parent
78bcf5546b
commit
695bdb3841
@ -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 ],
|
||||
)
|
||||
|
@ -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:
|
@ -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;
|
||||
|
||||
|
@ -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 = []
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user