util: Move glib event loop workaround to glibcompat

This way it can be used from other places as well.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Martin Kletzander 2021-03-04 09:34:19 +01:00
parent f81d504b71
commit 8964564550
6 changed files with 64 additions and 30 deletions

View File

@ -1046,6 +1046,9 @@ 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

@ -0,0 +1,11 @@
#
# 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

@ -124,6 +124,12 @@ 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

View File

@ -211,3 +211,36 @@ vir_g_strdup_vprintf(const char *msg, va_list args)
abort();
return ret;
}
/*
* If the last reference to a GSource is released in a non-main
* thread we're exposed to a race condition that causes a
* crash:
*
* https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1358
*
* Thus we're using an idle func to release our ref...
*
* ...but this imposes a significant performance penalty on
* I/O intensive workloads which are sensitive to the iterations
* of the event loop, so avoid the workaround if we know we have
* new enough glib.
*
* The function below is used from a header file definition.
*
* Drop when min glib >= 2.64.0
*/
#if GLIB_CHECK_VERSION(2, 64, 0) != TRUE
gboolean
virEventGLibSourceUnrefIdle(gpointer data)
{
GSource *src = data;
g_source_unref(src);
return FALSE;
}
#endif

View File

@ -84,3 +84,14 @@ char *vir_g_strdup_vprintf(const char *msg, va_list args)
#define g_canonicalize_filename vir_g_canonicalize_filename
#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

View File

@ -185,36 +185,6 @@ virEventGLibHandleFind(int watch)
return NULL;
}
/*
* If the last reference to a GSource is released in a non-main
* thread we're exposed to a race condition that causes a
* crash:
*
* https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1358
*
* Thus we're using an idle func to release our ref...
*
* ...but this imposes a significant performance penalty on
* I/O intensive workloads which are sensitive to the iterations
* of the event loop, so avoid the workaround if we know we have
* new enough glib.
*/
#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)
static gboolean
virEventGLibSourceUnrefIdle(gpointer data)
{
GSource *src = data;
g_source_unref(src);
return FALSE;
}
#endif
static void
virEventGLibHandleUpdate(int watch,