diff --git a/meson.build b/meson.build index c225df42d4..e5d5c4e14d 100644 --- a/meson.build +++ b/meson.build @@ -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 ], ) diff --git a/src/libvirt_glib_crash_workaround.syms b/src/libvirt_glib_crash_workaround.syms new file mode 100644 index 0000000000..249058b65b --- /dev/null +++ b/src/libvirt_glib_crash_workaround.syms @@ -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: diff --git a/src/meson.build b/src/meson.build index f13b85b74e..70a5a83eea 100644 --- a/src/meson.build +++ b/src/meson.build @@ -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 diff --git a/src/util/glibcompat.c b/src/util/glibcompat.c index 9f0f7f015c..fe19ffa87b 100644 --- a/src/util/glibcompat.c +++ b/src/util/glibcompat.c @@ -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 diff --git a/src/util/glibcompat.h b/src/util/glibcompat.h index 6463c4179a..9c52843274 100644 --- a/src/util/glibcompat.h +++ b/src/util/glibcompat.h @@ -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 diff --git a/src/util/vireventglib.c b/src/util/vireventglib.c index 193b3bfde2..88e3ec6d5d 100644 --- a/src/util/vireventglib.c +++ b/src/util/vireventglib.c @@ -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,