Backport a patch to fix a rare multithreaded crash
This commit is contained in:
parent
2a99a8873e
commit
c6d06c9cce
1
.libgusb.metadata
Normal file
1
.libgusb.metadata
Normal file
@ -0,0 +1 @@
|
|||||||
|
7291e7eda10fd045cec4a0b8d47de5ef6f4667f5 libgusb-0.3.8.tar.xz
|
126
idle-events-mutex.patch
Normal file
126
idle-events-mutex.patch
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
diff -urNp libgusb-0.3.8.old/gusb/gusb-context.c libgusb-0.3.8/gusb/gusb-context.c
|
||||||
|
--- libgusb-0.3.8.old/gusb/gusb-context.c 2023-07-31 10:27:45.903816362 +0100
|
||||||
|
+++ libgusb-0.3.8/gusb/gusb-context.c 2023-07-31 10:41:22.973605806 +0100
|
||||||
|
@@ -54,6 +54,9 @@ struct _GUsbContextPrivate
|
||||||
|
GUsbContextFlags flags;
|
||||||
|
libusb_context *ctx;
|
||||||
|
libusb_hotplug_callback_handle hotplug_id;
|
||||||
|
+ GPtrArray *idle_events;
|
||||||
|
+ GMutex idle_events_mutex;
|
||||||
|
+ guint idle_events_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* not defined in FreeBSD */
|
||||||
|
@@ -123,12 +126,18 @@ g_usb_context_dispose (GObject *object)
|
||||||
|
g_source_remove (priv->hotplug_poll_id);
|
||||||
|
priv->hotplug_poll_id = 0;
|
||||||
|
}
|
||||||
|
+ if (priv->idle_events_id > 0) {
|
||||||
|
+ g_source_remove(priv->idle_events_id);
|
||||||
|
+ priv->idle_events_id = 0;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->main_ctx, g_main_context_unref);
|
||||||
|
g_clear_pointer (&priv->devices, g_ptr_array_unref);
|
||||||
|
g_clear_pointer (&priv->dict_usb_ids, g_hash_table_unref);
|
||||||
|
g_clear_pointer (&priv->dict_replug, g_hash_table_unref);
|
||||||
|
g_clear_pointer (&priv->ctx, libusb_exit);
|
||||||
|
+ g_clear_pointer(&priv->idle_events, g_ptr_array_unref);
|
||||||
|
+ g_mutex_clear(&priv->idle_events_mutex);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (g_usb_context_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
@@ -377,23 +386,48 @@ g_usb_context_idle_helper_free (GUsbCont
|
||||||
|
g_free (helper);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static gpointer
|
||||||
|
+g_usb_context_idle_helper_copy(gconstpointer src, gpointer user_data)
|
||||||
|
+{
|
||||||
|
+ GUsbContextIdleHelper *helper_src = (GUsbContextIdleHelper *)src;
|
||||||
|
+ GUsbContextIdleHelper *helper_dst = g_new0(GUsbContextIdleHelper, 1);
|
||||||
|
+ helper_dst->context = g_object_ref(helper_src->context);
|
||||||
|
+ helper_dst->dev = libusb_ref_device(helper_src->dev);
|
||||||
|
+ helper_dst->event = helper_src->event;
|
||||||
|
+ return helper_dst;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* always in the main thread */
|
||||||
|
static gboolean
|
||||||
|
g_usb_context_idle_hotplug_cb (gpointer user_data)
|
||||||
|
{
|
||||||
|
- GUsbContextIdleHelper *helper = (GUsbContextIdleHelper *) user_data;
|
||||||
|
+ GUsbContext *context = G_USB_CONTEXT(user_data);
|
||||||
|
+ GUsbContextPrivate *priv = context->priv;
|
||||||
|
+ g_autoptr(GPtrArray) idle_events = NULL;
|
||||||
|
|
||||||
|
- switch (helper->event) {
|
||||||
|
- case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
|
||||||
|
- g_usb_context_add_device (helper->context, helper->dev);
|
||||||
|
- break;
|
||||||
|
- case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
|
||||||
|
- g_usb_context_remove_device (helper->context, helper->dev);
|
||||||
|
- break;
|
||||||
|
- default:
|
||||||
|
- break;
|
||||||
|
+ /* drain the idle events with the lock held */
|
||||||
|
+ g_mutex_lock(&priv->idle_events_mutex);
|
||||||
|
+ idle_events = g_ptr_array_copy(priv->idle_events, g_usb_context_idle_helper_copy, NULL);
|
||||||
|
+ g_ptr_array_set_size(priv->idle_events, 0);
|
||||||
|
+ priv->idle_events_id = 0;
|
||||||
|
+ g_mutex_unlock(&priv->idle_events_mutex);
|
||||||
|
+
|
||||||
|
+ /* run the callbacks when not locked */
|
||||||
|
+ for (guint i = 0; i < idle_events->len; i++) {
|
||||||
|
+ GUsbContextIdleHelper *helper = g_ptr_array_index(idle_events, i);
|
||||||
|
+ switch (helper->event) {
|
||||||
|
+ case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
|
||||||
|
+ g_usb_context_add_device(helper->context, helper->dev);
|
||||||
|
+ break;
|
||||||
|
+ case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
|
||||||
|
+ g_usb_context_remove_device(helper->context, helper->dev);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
- g_usb_context_idle_helper_free (helper);
|
||||||
|
+ /* all done */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -405,13 +439,19 @@ g_usb_context_hotplug_cb (struct libusb_
|
||||||
|
{
|
||||||
|
GUsbContext *context = G_USB_CONTEXT (user_data);
|
||||||
|
GUsbContextIdleHelper *helper;
|
||||||
|
+ GUsbContextPrivate *priv = context->priv;
|
||||||
|
+ g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&priv->idle_events_mutex);
|
||||||
|
+
|
||||||
|
+ g_assert(locker != NULL);
|
||||||
|
|
||||||
|
helper = g_new0 (GUsbContextIdleHelper, 1);
|
||||||
|
- helper->context = context;
|
||||||
|
+ helper->context = g_object_ref(context);
|
||||||
|
helper->dev = libusb_ref_device (dev);
|
||||||
|
helper->event = event;
|
||||||
|
|
||||||
|
- g_idle_add (g_usb_context_idle_hotplug_cb, helper);
|
||||||
|
+ g_ptr_array_add(priv->idle_events, helper);
|
||||||
|
+ if (priv->idle_events_id == 0)
|
||||||
|
+ priv->idle_events_id = g_idle_add(g_usb_context_idle_hotplug_cb, context);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -605,6 +645,11 @@ g_usb_context_init (GUsbContext *context
|
||||||
|
priv->dict_usb_ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
priv->dict_replug = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free, NULL);
|
||||||
|
+
|
||||||
|
+ /* to escape the thread into the mainloop */
|
||||||
|
+ g_mutex_init(&priv->idle_events_mutex);
|
||||||
|
+ priv->idle_events =
|
||||||
|
+ g_ptr_array_new_with_free_func((GDestroyNotify)g_usb_context_idle_helper_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
11
libgusb.spec
11
libgusb.spec
@ -1,11 +1,14 @@
|
|||||||
Summary: GLib wrapper around libusb1
|
Summary: GLib wrapper around libusb1
|
||||||
Name: libgusb
|
Name: libgusb
|
||||||
Version: 0.3.8
|
Version: 0.3.8
|
||||||
Release: 1%{?dist}
|
Release: 2%{?dist}
|
||||||
License: LGPLv2+
|
License: LGPLv2+
|
||||||
URL: https://github.com/hughsie/libgusb
|
URL: https://github.com/hughsie/libgusb
|
||||||
Source0: http://people.freedesktop.org/~hughsient/releases/%{name}-%{version}.tar.xz
|
Source0: http://people.freedesktop.org/~hughsient/releases/%{name}-%{version}.tar.xz
|
||||||
|
|
||||||
|
# backport from upstream
|
||||||
|
Patch0: idle-events-mutex.patch
|
||||||
|
|
||||||
BuildRequires: glib2-devel >= 2.38.0
|
BuildRequires: glib2-devel >= 2.38.0
|
||||||
BuildRequires: gobject-introspection-devel
|
BuildRequires: gobject-introspection-devel
|
||||||
BuildRequires: gtk-doc
|
BuildRequires: gtk-doc
|
||||||
@ -26,7 +29,7 @@ Requires: %{name} = %{version}-%{release}
|
|||||||
GLib headers and libraries for gusb.
|
GLib headers and libraries for gusb.
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q
|
%autosetup -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
%meson -Dvapi=true -Dtests=true
|
%meson -Dvapi=true -Dtests=true
|
||||||
@ -55,6 +58,10 @@ GLib headers and libraries for gusb.
|
|||||||
%{_datadir}/vala/vapi/gusb.vapi
|
%{_datadir}/vala/vapi/gusb.vapi
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Jul 31 2023 Richard Hughes <richard@hughsie.com> 0.3.8-2
|
||||||
|
- Backport a patch to fix a rare multithreaded crash on device replug
|
||||||
|
- Resolves: rhbz#2227760
|
||||||
|
|
||||||
* Wed Oct 06 2021 Richard Hughes <richard@hughsie.com> 0.3.8-1
|
* Wed Oct 06 2021 Richard Hughes <richard@hughsie.com> 0.3.8-1
|
||||||
- New upstream version
|
- New upstream version
|
||||||
- Add new API requested by fwupd
|
- Add new API requested by fwupd
|
||||||
|
Loading…
Reference in New Issue
Block a user