From f482e2a456491056e7576c1b52ead08429542631 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 11 Feb 2022 09:56:04 +0100 Subject: [PATCH] QDesktopServices: fix ABA problem in QOpenUrlHandlerRegistry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The registry is designed to be thread-safe, as is openUrl(), and handlers are required to be thread-safe, too: "the handler will always be called from within the same thread that calls QDesktopServices::openUrl()". The handlerDestroyed() slot was invoked using AutoConnection semantics, which, if the registry and the handler happen to not be on the same thread, is QueuedConnection, which means there's a window in which the handler is destroyed, but it's still listed in the registry, and a call to openUrl() may make a call to the (deleted) handler. Worse, if a handler is deleted and new one registered they may end up on the same address (ABA, or rather, AA problem), and then the delayed call to handlerDestroyed() may remove the entries to the new handler, as well as those to the old. Fix by using Qt::DirectConnection. This fixes the ABA problem, but doesn't completely fix the partially-destroyed problem, since QObject::destroyed() is simply too late. We need to require explicit unsetUrlHandler() calls, which should happen before destruction of the handler object starts. [ChangeLog][QtGui][QDesktopServices] Fixed a bug where destroying and re-creating a handler object in quick succession could cause the registration for the handler to be lost. Fixes: QTBUG-100778 Pick-to: 6.3 6.2 5.15 Change-Id: I76fd81724504cc7f38ac262b43e3e9539fe5ebca Reviewed-by: Sona Kurazyan Reviewed-by: MÃ¥rten Nordheim Reviewed-by: Thiago Macieira --- src/gui/util/qdesktopservices.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp index 1e77dcb3ae..fd3761a473 100644 --- a/src/gui/util/qdesktopservices.cpp +++ b/src/gui/util/qdesktopservices.cpp @@ -324,7 +324,8 @@ void QDesktopServices::setUrlHandler(const QString &scheme, QObject *receiver, c h.name = method; registry->handlers.insert(scheme.toLower(), h); QObject::connect(receiver, SIGNAL(destroyed(QObject*)), - registry, SLOT(handlerDestroyed(QObject*))); + registry, SLOT(handlerDestroyed(QObject*)), + Qt::DirectConnection); } /*!