Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault when closing #7

Closed
The-Compiler opened this issue Oct 1, 2014 · 13 comments
Closed

Segfault when closing #7

The-Compiler opened this issue Oct 1, 2014 · 13 comments
Assignees

Comments

@The-Compiler
Copy link
Member

We still have some segfaults when closing, usually with a corrupted stack trace:

#5  0x00007fffde97a700 in ?? ()
#6  0x00007ffff57573be in ?? () from /usr/lib/libQt5Core.so.5
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

There's an user who can reproduce it by letting qutebrowser run on duckduckgo for ~10 hours and then closing it with the "x"-button in his window manager.

Maybe a solution is to delete the QApplication object properly.

References:

http://python.6.x6.nabble.com/Application-crash-on-exit-under-Linux-td5067510.html
http://stackoverflow.com/questions/5506781/pyqt4-application-on-windows-is-crashing-on-exit
http://qt-project.org/forums/viewthread/27196
http://stackoverflow.com/questions/11945183/what-are-good-practices-for-avoiding-crashes-hangs-in-pyqt
https://github.com/Xinkai/XwareDesktop/issues/25

@The-Compiler The-Compiler self-assigned this Oct 1, 2014
@The-Compiler The-Compiler added this to the v0.1 milestone Oct 1, 2014
@The-Compiler
Copy link
Member Author

Some attempted fixes are in the segfault branch, but it's not tested yet if they fix the issue.

@The-Compiler
Copy link
Member Author

Xinkai/XwareDesktop does this:

-    sys.exit(app.exec())
+    code = app.exec()
+    for w in QApplication.topLevelWindows():
+        del w
+    del app
+    sys.exit(code)

@The-Compiler
Copy link
Member Author

I tried to reproduce it (on the master branch) with no luck. About 8 hours of running with Arch, Debian VM and Ubuntu VM, and closing via the close-button worked normally.

@The-Compiler
Copy link
Member Author

@The-Compiler
Copy link
Member Author

@The-Compiler
Copy link
Member Author

Another one:

#0  QString (other=..., this=0x7f5a68bbcca0) at ../../include/QtCore/../../src/corelib/tools/qstring.h:814
#1  dbusServiceString () at qdbusintegrator.cpp:82
#2  QDBusConnectionPrivate::isServiceRegisteredByThread (this=0x2c4fea0, serviceName=...) at qdbusintegrator.cpp:2494
#3  0x00007f5a6b72956e in QDBusConnectionPrivate::sendWithReply (this=0x2c4fea0, message=..., sendMode=1, timeout=-1) at qdbusintegrator.cpp:1940
#4  0x00007f5a6b7159eb in QDBusConnection::call (this=0x7f5a1401a790, message=..., mode=<optimized out>, timeout=<optimized out>) at qdbusconnection.cpp:584
#5  0x00007f5a6b733bf8 in QDBusAbstractInterfacePrivate::property (this=0x7f5a1401a720, mp=..., returnValuePtr=0x1e) at qdbusabstractinterface.cpp:146
#6  0x00007f5a6b735c96 in QDBusAbstractInterfaceBase::qt_metacall (this=this@entry=0x7f5a1401a680, _c=_c@entry=QMetaObject::ReadProperty, _id=<optimized out>, _a=_a@entry=0x7f5a68bbd1c0) at qdbusabstractinterface.cpp:257
#7  0x00007f5a6b735e45 in QDBusAbstractInterface::qt_metacall (this=this@entry=0x7f5a1401a680, _c=_c@entry=QMetaObject::ReadProperty, _id=<optimized out>, _a=_a@entry=0x7f5a68bbd1c0) at .moc/moc_qdbusabstractinterface.cpp:95
#8  0x00007f5a6b737cc1 in QDBusInterface::qt_metacall (this=0x7f5a1401a680, _c=QMetaObject::ReadProperty, _id=<optimized out>, _a=0x7f5a68bbd1c0) at qdbusinterface.cpp:262
#9  0x00007f5a80920507 in QMetaProperty::read (this=this@entry=0x7f5a68bbd260, object=object@entry=0x7f5a1401a680) at kernel/qmetaobject.cpp:2848
#10 0x00007f5a809425f7 in QObject::property (this=0x7f5a1401a680, name=name@entry=0x7f5a23be3cf7 "Ssid") at kernel/qobject.cpp:3861
#11 0x00007f5a23bc7a6f in QNetworkManagerInterfaceAccessPoint::ssid (this=<optimized out>) at qnetworkmanagerservice.cpp:266
#12 0x00007f5a23bd4514 in QNetworkManagerEngine::newAccessPoint (this=0x2c5c470, path=..., objectPath=...) at qnetworkmanagerengine.cpp:563
#13 0x00007f5a23be2bf5 in QNetworkManagerEngine::qt_static_metacall (_o=0x7f5a1401cc80, _c=45516704, _id=30, _a=0x1) at .moc/moc_qnetworkmanagerengine.cpp:142
#14 0x00007f5a8094365d in QMetaObject::activate (sender=0x7f5a14003740, signalOffset=<optimized out>, local_signal_index=local_signal_index@entry=1, argv=argv@entry=0x7f5a68bbd520) at kernel/qobject.cpp:3681
#15 0x00007f5a80943ac7 in QMetaObject::activate (sender=<optimized out>, m=m@entry=0x7f5a23ded840 <QNetworkManagerInterfaceDeviceWireless::staticMetaObject>, local_signal_index=local_signal_index@entry=1, 
    argv=argv@entry=0x7f5a68bbd520) at kernel/qobject.cpp:3547
#16 0x00007f5a23be0aea in QNetworkManagerInterfaceDeviceWireless::accessPointAdded (this=<optimized out>, _t1=..., _t2=...) at .moc/moc_qnetworkmanagerservice.cpp:700
#17 0x00007f5a23be1ac6 in QNetworkManagerInterfaceDeviceWireless::qt_static_metacall (_o=0x7f5a14003740, _c=45516704, _id=30, _a=0x1) at .moc/moc_qnetworkmanagerservice.cpp:607
#18 0x00007f5a8094365d in QMetaObject::activate (sender=sender@entry=0x7f5a140081c0, signalOffset=<optimized out>, local_signal_index=local_signal_index@entry=1, argv=argv@entry=0x7f5a68bbd6a0) at kernel/qobject.cpp:3681
#19 0x00007f5a80943ac7 in QMetaObject::activate (sender=sender@entry=0x7f5a140081c0, m=m@entry=0x7f5a23ded140 <QNmDBusHelper::staticMetaObject>, local_signal_index=local_signal_index@entry=1, argv=argv@entry=0x7f5a68bbd6a0)
    at kernel/qobject.cpp:3547
#20 0x00007f5a23bdfe3a in QNmDBusHelper::pathForAccessPointAdded (this=this@entry=0x7f5a140081c0, _t1=..., _t2=...) at .moc/moc_qnmdbushelper.cpp:234
#21 0x00007f5a23bc5c76 in QNmDBusHelper::slotAccessPointAdded (this=0x7f5a140081c0, path=...) at qnmdbushelper.cpp:83
#22 0x00007f5a23be02ca in QNmDBusHelper::qt_static_metacall (_o=0x7f5a140081c0, _c=45516704, _c@entry=QMetaObject::InvokeMetaMethod, _id=30, _id@entry=6, _a=0x1, _a@entry=0x7f5a68bbd8c0) at .moc/moc_qnmdbushelper.cpp:111
#23 0x00007f5a23be05e3 in QNmDBusHelper::qt_metacall (this=0x7f5a140081c0, _c=QMetaObject::InvokeMetaMethod, _id=6, _a=0x7f5a68bbd8c0) at .moc/moc_qnmdbushelper.cpp:213
#24 0x00007f5a6b725a47 in QDBusConnectionPrivate::deliverCall (this=0x7f5a1401cc80, object=0x2b687a0, msg=..., metaTypes=..., slotIdx=335574247) at qdbusintegrator.cpp:991
#25 0x00007f5a8094452a in QObject::event (this=0x7f5a140081c0, e=<optimized out>) at kernel/qobject.cpp:1241
#26 0x00007f5a6f05df3c in QApplicationPrivate::notify_helper (this=0x29c3840, receiver=0x7f5a140081c0, e=0x2fabfe0) at kernel/qapplication.cpp:3499
#27 0x00007f5a6f063380 in QApplication::notify (this=0x2665b70, receiver=0x7f5a140081c0, e=0x2fabfe0) at kernel/qapplication.cpp:3282
#28 0x00007f5a6fa4738c in sipQApplication::notify (this=0x2665b70, a0=0x7f5a140081c0, a1=0x2fabfe0) at sipQtWidgetsQApplication.cpp:349
#29 0x00007f5a8091498b in QCoreApplication::notifyInternal (this=0x2665b70, receiver=0x7f5a140081c0, event=event@entry=0x2fabfe0) at kernel/qcoreapplication.cpp:935
#30 0x00007f5a80916953 in sendEvent (event=0x2fabfe0, receiver=<optimized out>) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:237
#31 QCoreApplicationPrivate::sendPostedEvents (receiver=receiver@entry=0x0, event_type=event_type@entry=0, data=0x2c4ea00) at kernel/qcoreapplication.cpp:1539
#32 0x00007f5a80916f58 in QCoreApplication::sendPostedEvents (receiver=receiver@entry=0x0, event_type=event_type@entry=0) at kernel/qcoreapplication.cpp:1397
#33 0x00007f5a8096bf43 in postEventSourceDispatch (s=0x7f5a140012f0) at kernel/qeventdispatcher_glib.cpp:279
#34 0x00007f5a82230a0d in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
#35 0x00007f5a82230cf8 in ?? () from /usr/lib/libglib-2.0.so.0
#36 0x00007f5a82230dac in g_main_context_iteration () from /usr/lib/libglib-2.0.so.0
#37 0x00007f5a8096c337 in QEventDispatcherGlib::processEvents (this=0x7f5a140008e0, flags=...) at kernel/qeventdispatcher_glib.cpp:426
#38 0x00007f5a809123b2 in QEventLoop::exec (this=this@entry=0x7f5a68bbdec0, flags=..., flags@entry=...) at kernel/qeventloop.cpp:212
#39 0x00007f5a80723354 in QThread::exec (this=<optimized out>) at thread/qthread.cpp:511
#40 0x00007f5a8072837e in QThreadPrivate::start (arg=0x2aad780) at thread/qthread_unix.cpp:345
#41 0x00007f5a85f23314 in start_thread () from /usr/lib/libpthread.so.0
#42 0x00007f5a85c615bd in clone () from /usr/lib/libc.so.6

@The-Compiler
Copy link
Member Author

Removing this from v0.1 - one source of crashes has been identified and fixed at least.

@The-Compiler The-Compiler removed this from the v0.1 milestone Dec 13, 2014
@The-Compiler
Copy link
Member Author

Another one, with v0.1 on Windows when restarting from exception handler:

Qt5WebKit!QWebSettings::QWebSettings+1632 
Qt5WebKit!QWebSettings::~QWebSettings+30 
Qt5WebKit!QWebPageAdapter::~QWebPageAdapter+41 
Qt5WebKitWidgets!QWebPage::setViewportSize+1f4 
Qt5WebKitWidgets!QWebPage::~QWebPage+26 
QtWebKitWidgets!PyInit_QtWebKitWidgets+177e2 
Qt5WebKitWidgets!QWebView::metaObject+f3 
Qt5WebKitWidgets!QWebView::qt_metacall+34e 
Qt5WebKitWidgets!QWebView::~QWebView+31 
QtWebKitWidgets!PyInit_QtWebKitWidgets+20fad 
Qt5Core!QObject::event+86 
Qt5Widgets!QWidget::event+d4b 
QtWebKitWidgets!PyInit_QtWebKitWidgets+1c0dd 
Qt5Widgets!QApplicationPrivate::notify_helper+f6 
Qt5Widgets!QApplication::notify+1eca 
QtWidgets!PyInit_QtWidgets+2e7a8 
Qt5Core!QCoreApplication::notifyInternal+6f 
Qt5Core!QCoreApplicationPrivate::sendPostedEvents+258 
Qt5Core!QAbstractEventDispatcherPrivate::QAbstractEventDispatcherPrivate+e0 
Qt5Core!QThread::wait+12e 
Qt5Core!QThreadPoolPrivate::reset+cd 
Qt5Core!QThreadPool::waitForDone+25 
Qt5Network!QHostInfo::~QHostInfo+5f0 
Qt5Network!QHostInfo::~QHostInfo+923 
Qt5Network!QHostInfo::~QHostInfo+a14 
Qt5Network!QUdpSocket::metaObject+1a5b 
Qt5Network!QUdpSocket::metaObject+cb7 
Qt5Network!QUdpSocket::metaObject+f01 
ntdll!LdrShutdownProcess+1db 
ntdll!RtlExitUserProcess+90 
msvcr100!cinit+20d 
python34!PyOS_URandom+1af945 
python34!PyOS_URandom+1afad1 
python34!PyOS_URandom+1afc5c 
QtCore!PyInit_QtCore+127b4e 
QtCore!PyInit_QtCore+127c26 
Qt5Core!QMetaObject::activate+622 
QtCore!PyInit_QtCore+1242fa 
QtCore!PyInit_QtCore+124499 
python34!PyOS_URandom+fcd3d 
...
python34!PyOS_URandom+16ef3b 
sip!PyInit_sip+1410 
QtCore+2c23 
QtCore!PyInit_QtCore+b5901 
Qt5Core!QCoreApplicationPrivate::sendThroughApplicationEventFilters+f5 
Qt5Widgets!QApplicationPrivate::notify_helper+1e 
Qt5Widgets!QApplication::notify+1eca 
QtWidgets!PyInit_QtWidgets+2e7a8 
Qt5Core!QCoreApplication::notifyInternal+6f 
Qt5Gui!QGuiApplicationPrivate::processKeyEvent+a9 
Qt5Gui!QGuiApplicationPrivate::processWindowSystemEvent+1a1 
Qt5Gui!QWindowSystemInterface::sendWindowSystemEvents+73 
Qt5Core!QEventDispatcherWin32Private::QEventDispatcherWin32Private+378 
user32!UserCallWinProcCheckWow+1ad 
user32!DispatchMessageWorker+3b5 
Qt5Core!QEventDispatcherWin32::processEvents+426 
qwindows+1fcd1 
Qt5Core!QEventLoop::exec+1cd 
Qt5Core!QCoreApplication::exec+189 

@arp242
Copy link
Contributor

arp242 commented May 29, 2015

Observed after leaving it open on :help for about 20 minutes and pressing <C-q>.

#0  0x00007fe501d2266d in QNetworkConfigurationManagerPrivate::pollEngines() () from /usr/lib/libQt5Network.so.5
#1  0x00007fe501d8cdcd in ?? () from /usr/lib/libQt5Network.so.5
#2  0x00007fe5102c5ff9 in QMetaObject::activate(QObject*, int, int, void**) () from /usr/lib/libQt5Core.so.5
#3  0x00007fe5102d3df8 in QTimer::timerEvent(QTimerEvent*) () from /usr/lib/libQt5Core.so.5
#4  0x00007fe5102c6d13 in QObject::event(QEvent*) () from /usr/lib/libQt5Core.so.5
#5  0x00007fe50b3ec3dc in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQt5Widgets.so.5
#6  0x00007fe50b3f1820 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/libQt5Widgets.so.5
#7  0x00007fe50bd3219e in ?? () from /usr/lib/python3.4/site-packages/PyQt5/QtWidgets.so
#8  0x00007fe5102959eb in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/libQt5Core.so.5
#9  0x00007fe5102eccdd in QTimerInfoList::activateTimers() () from /usr/lib/libQt5Core.so.5
#10 0x00007fe5102ed121 in ?? () from /usr/lib/libQt5Core.so.5
#11 0x00007fe5118fe9fd in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
#12 0x00007fe5118fece0 in ?? () from /usr/lib/libglib-2.0.so.0
#13 0x00007fe5118fed8c in g_main_context_iteration () from /usr/lib/libglib-2.0.so.0
#14 0x00007fe5102eddfc in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/libQt5Core.so.5
#15 0x00007fe510293482 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/libQt5Core.so.5
#16 0x00007fe5100a51f4 in QThread::exec() () from /usr/lib/libQt5Core.so.5
#17 0x00007fe5100aa18e in ?? () from /usr/lib/libQt5Core.so.5
#18 0x00007fe5182ec354 in start_thread () from /usr/lib/libpthread.so.0
#19 0x00007fe51802abfd in clone () from /usr/lib/libc.so.6

Qt 5.4.1

@The-Compiler
Copy link
Member Author

This one seems to be a Qt bug which was fixed for Qt 5.4.2, which should be released in the next few days.

@fosskers
Copy link

If it helps at all, I notice quite often that systemd-coredump goes nuts when I close qutebrowser. I'm on xmonad and close it with super+shift+c, as per the default.

@The-Compiler
Copy link
Member Author

It seems a lot better to me now (with recent Qt/PyQt versions) as it used to be, so I'm closing this and hope it's indeed the case.

@The-Compiler
Copy link
Member Author

Old code with some stuff I tried from the segfault branch:

commit b7b1fe9518688bc668fd65a993f53dde73c5277c
Author: Florian Bruhin <git@the-compiler.org>
Date:   Mon Oct 13 08:22:12 2014 +0200

    Fix downloadModel rowCount

diff --git a/qutebrowser/models/downloadmodel.py b/qutebrowser/models/downloadmodel.py
index f7f1138..a256ac7 100644
--- a/qutebrowser/models/downloadmodel.py
+++ b/qutebrowser/models/downloadmodel.py
@@ -105,4 +105,9 @@ class DownloadModel(QAbstractListModel):
         if parent.isValid():
             # We don't have children
             return 0
-        return len(objreg.get('download-manager').downloads)
+        try:
+            download_manager = objreg.get('download-manager')
+        except KeyError:
+            return 0
+        else:
+            return len(download_manager.downloads)

commit d74345d77e05c292ee1f25530432ab27764e5f93
Author: Florian Bruhin <git@the-compiler.org>
Date:   Mon Oct 13 04:10:24 2014 +0200

    quick fix for KeyError on shutdown

diff --git a/qutebrowser/widgets/mainwindow.py b/qutebrowser/widgets/mainwindow.py
index d8dd816..199b1b3 100644
--- a/qutebrowser/widgets/mainwindow.py
+++ b/qutebrowser/widgets/mainwindow.py
@@ -160,9 +160,12 @@ class MainWindow(QWidget):
             e: The QResizeEvent
         """
         super().resizeEvent(e)
-        self.resize_completion()
-        self._downloadview.updateGeometry()
-        self._tabbed_browser.tabBar().refresh()
+        try:
+            self.resize_completion()
+            self._downloadview.updateGeometry()
+            self._tabbed_browser.tabBar().refresh()
+        except KeyError:
+            pass

     def closeEvent(self, e):
         """Override closeEvent to display a confirmation if needed."""

commit 725468414b47cce898a57cda8b78b4effa964cee
Author: Florian Bruhin <git@the-compiler.org>
Date:   Tue Sep 30 06:32:41 2014 +0200

    Make exit debugging a lot more verbose

diff --git a/qutebrowser/app.py b/qutebrowser/app.py
index 04a81ba..ed69d1f 100644
--- a/qutebrowser/app.py
+++ b/qutebrowser/app.py
@@ -19,6 +19,7 @@

 """Initialization of qutebrowser and application-wide things."""

+import gc
 import os
 import sys
 import subprocess
@@ -660,6 +661,10 @@ class Application(QApplication):
         # pylint: disable=too-many-branches, too-many-statements
         # FIXME refactor this
         log.destroy.debug("Stage 2 of shutting down...")
+        if self._args.debug_exit:
+            print("Now logging shutdown.", file=sys.stderr)
+            debug.trace_lines(True)
+            gc.set_debug(gc.DEBUG_LEAK)
         # Remove eventfilter
         try:
             log.destroy.debug("Removing eventfilter...")
@@ -733,7 +738,4 @@ class Application(QApplication):
     def exit(self, status):
         """Extend QApplication::exit to log the event."""
         log.destroy.debug("Now calling QApplication::exit.")
-        if self._args.debug_exit:
-            print("Now logging late shutdown.", file=sys.stderr)
-            debug.trace_lines(True)
         super().exit(status)

commit 59640888afe0fee60b89445235c8550b13a62ccc
Author: Florian Bruhin <git@the-compiler.org>
Date:   Tue Sep 30 06:17:09 2014 +0200

    Clear object registries on shutdown.

diff --git a/qutebrowser/app.py b/qutebrowser/app.py
index b28703e..04a81ba 100644
--- a/qutebrowser/app.py
+++ b/qutebrowser/app.py
@@ -722,6 +722,8 @@ class Application(QApplication):
         # If we don't kill our custom handler here we might get segfaults
         log.destroy.debug("Deactiving message handler...")
         qInstallMessageHandler(None)
+        log.destroy.debug("Cleaning up object registry...")
+        objreg.clear()
         # Now we can hopefully quit without segfaults
         log.destroy.debug("Deferring QApplication::exit...")
         # We use a singleshot timer to exit here to minimize the likelyhood of
diff --git a/qutebrowser/utils/objreg.py b/qutebrowser/utils/objreg.py
index 6f233cc..b94dcdd 100644
--- a/qutebrowser/utils/objreg.py
+++ b/qutebrowser/utils/objreg.py
@@ -84,6 +84,12 @@ meta_registry = ObjectRegistry()
 meta_registry['global'] = global_registry


+def clear():
+    """Clear all object registries on shutdown."""
+    global_registry.clear()
+    meta_registry.clear()
+
+
 def _get_registry(scope):
     """Get the correct registry for a given scope."""
     if scope == 'global':
diff --git a/qutebrowser/widgets/webview.py b/qutebrowser/widgets/webview.py
index 71cbfab..f7e6ded 100644
--- a/qutebrowser/widgets/webview.py
+++ b/qutebrowser/widgets/webview.py
@@ -260,6 +260,7 @@ class WebView(QWebView):
         # Copied from:
         # https://code.google.com/p/webscraping/source/browse/webkit.py#325
         self.setPage(None)
+        self.registry.clear()

     def openurl(self, url):
         """Open a URL in the browser.

commit 8e4af9bce2f7e6675ae57f2650ae0e230a184fd3
Author: Florian Bruhin <git@the-compiler.org>
Date:   Tue Sep 30 06:16:59 2014 +0200

    Delete reference to app explicitely.

diff --git a/qutebrowser/qutebrowser.py b/qutebrowser/qutebrowser.py
index e2f1578..c9269b7 100644
--- a/qutebrowser/qutebrowser.py
+++ b/qutebrowser/qutebrowser.py
@@ -114,4 +114,5 @@ def main():
     QtWidgets.qApp = app
     ret = app.exec_()
     QtWidgets.qApp = None
+    del app
     return ret

The-Compiler added a commit that referenced this issue Mar 29, 2021
This reverts commit c6cf306.

Seems to cause segfaults:

  #0  0x00007ffff5cecbcc in void doActivate<false>(QObject*, int, void**) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
  #1  0x00007ffff5be4e31 in QIODevice::channelReadyRead(int) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
  #2  0x00007fffeffccb54 in QAbstractSocketPrivate::canReadNotification() () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Network.so.5
  #3  0x00007fffeffdf061 in QReadNotifier::event(QEvent*) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Network.so.5
  #4  0x00007ffff269e43c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Widgets.so.5
  #5  0x00007ffff26a4f20 in QApplication::notify(QObject*, QEvent*) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Widgets.so.5
  #6  0x00007ffff318d0d6 in sipQApplication::notify(QObject*, QEvent*) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/QtWidgets.abi3.so
  #7  0x00007ffff5cb4808 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
  #8  0x00007ffff5d10d98 in socketNotifierSourceDispatch(_GSource*, int (*)(void*), void*) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
  #9  0x00007ffff691df9c in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
  #10 0x00007ffff6971a49 in ?? () from /usr/lib/libglib-2.0.so.0
  #11 0x00007ffff691b6f1 in g_main_context_iteration () from /usr/lib/libglib-2.0.so.0
  #12 0x00007ffff5d101cc in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
  #13 0x00007ffff5cb321a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
  #14 0x00007ffff5cbc1d3 in QCoreApplication::exec() () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
The-Compiler added a commit that referenced this issue Mar 29, 2021
This reverts commit c6cf306.

Seems to cause segfaults:

  #0  0x00007ffff5cecbcc in void doActivate<false>(QObject*, int, void**) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
  #1  0x00007ffff5be4e31 in QIODevice::channelReadyRead(int) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
  #2  0x00007fffeffccb54 in QAbstractSocketPrivate::canReadNotification() () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Network.so.5
  #3  0x00007fffeffdf061 in QReadNotifier::event(QEvent*) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Network.so.5
  #4  0x00007ffff269e43c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Widgets.so.5
  #5  0x00007ffff26a4f20 in QApplication::notify(QObject*, QEvent*) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Widgets.so.5
  #6  0x00007ffff318d0d6 in sipQApplication::notify(QObject*, QEvent*) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/QtWidgets.abi3.so
  #7  0x00007ffff5cb4808 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
  #8  0x00007ffff5d10d98 in socketNotifierSourceDispatch(_GSource*, int (*)(void*), void*) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
  #9  0x00007ffff691df9c in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
  #10 0x00007ffff6971a49 in ?? () from /usr/lib/libglib-2.0.so.0
  #11 0x00007ffff691b6f1 in g_main_context_iteration () from /usr/lib/libglib-2.0.so.0
  #12 0x00007ffff5d101cc in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
  #13 0x00007ffff5cb321a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
  #14 0x00007ffff5cbc1d3 in QCoreApplication::exec() () from /home/florian/proj/qutebrowser/git/.tox/py39-pyqt515/lib/python3.9/site-packages/PyQt5/Qt5/lib/libQt5Core.so.5
The-Compiler added a commit that referenced this issue Dec 6, 2022
In bleeding tests, we started to get a segfault on the second test in
tests/unit/mainwindow/test_prompt.py, with a stacktrace like:

    Thread 1 "python" received signal SIGSEGV, Segmentation fault.
    0x00007ffff7b55912 in _PyFunction_Vectorcall (func=<function at remote 0x7fffc4368ca0>, stack=0x7fffd74656a8, nargsf=<optimized out>, kwnames=0x0) at Objects/call.c:341
    341	   if (((PyCodeObject *)f->fc_code)->co_flags & CO_OPTIMIZED) {
    (gdb) bt
    #0  0x00007ffff7b55912 in _PyFunction_Vectorcall (func=<function at remote 0x7fffc4368ca0>, stack=0x7fffd74656a8, nargsf=<optimized out>, kwnames=0x0) at Objects/call.c:341
    #1  0x00007ffff4e0b3f1 in PyQtSlot::call(_object*, _object*) const (this=0x555556c759c0, args=('/tmp/pytest-of-florian/pytest-70/test_simple_completion_1_next_0/test',), callable=<function at remote 0x7fffc4368ca0>)
        at ../../qpy/QtCore/qpycore_pyqtslot.cpp:247
    #2  PyQtSlot::invoke(void**, _object*, void*, bool) const (this=0x555556c759c0, qargs=<optimized out>, qargs@entry=0x7fffffff86c0, self=<optimized out>, self@entry=0x0, result=result@entry=0x0, no_receiver_check=<optimized out>)
        at ../../qpy/QtCore/qpycore_pyqtslot.cpp:159
    #3  0x00007ffff4e12213 in PyQtSlot::invoke(void**, bool) const (no_receiver_check=<optimized out>, qargs=0x7fffffff86c0, this=<optimized out>) at ../../qpy/QtCore/qpycore_pyqtslot.cpp:78
    #4  PyQtSlotProxy::unislot(void**) (qargs=0x7fffffff86c0, this=0x555557193e20) at ../../qpy/QtCore/qpycore_pyqtslotproxy.cpp:205
    #5  PyQtSlotProxy::unislot(void**) (qargs=0x7fffffff86c0, this=0x555557193e20) at ../../qpy/QtCore/qpycore_pyqtslotproxy.cpp:186
    #6  PyQtSlotProxy::qt_metacall(QMetaObject::Call, int, void**) (this=0x555557193e20, _c=<optimized out>, _id=0, _a=0x7fffffff86c0) at ../../qpy/QtCore/qpycore_pyqtslotproxy.cpp:170
    #7  0x00007ffff48bd91d in doActivate<false>(QObject*, int, void**) (sender=0x555556b3d680, signal_index=28, argv=0x7fffffff86c0) at kernel/qobject.cpp:3945
    #8  0x00007fffeff96aca in QFileSystemModel::directoryLoaded(QString const&) (this=<optimized out>, _t1=<optimized out>) at .moc/moc_qfilesystemmodel.cpp:272
    #9  0x00007ffff48b0be0 in QObject::event(QEvent*) (this=this@entry=0x555556b3d680, e=e@entry=0x7fff0c004af0) at kernel/qobject.cpp:1347
    #10 0x00007fffeff962ab in QFileSystemModel::event(QEvent*) (this=this@entry=0x555556b3d680, event=event@entry=0x7fff0c004af0) at dialogs/qfilesystemmodel.cpp:1748
    #11 0x00007ffff070995c in sipQFileSystemModel::event(QEvent*) (this=0x555556b3d680, a0=0x7fff0c004af0) at /usr/src/debug/pyqt5/PyQt5-5.15.7/build/QtWidgets/sipQtWidgetsQFileSystemModel.cpp:376
    [...]
    #23 0x00007ffff4da94ce in meth_QCoreApplication_processEvents(PyObject*, PyObject*, PyObject*) (sipArgs=<optimized out>, sipKwds=0x0) at /usr/src/debug/pyqt5/PyQt5-5.15.7/build/QtCore/sipQtCoreQCoreApplication.cpp:590
    [...]

from pytest-qt in Python:

    Current thread 0x00007fb366207740 (most recent call first):
    File ".../pytestqt/plugin.py", line 209 in _process_events
    File ".../pytestqt/plugin.py", line 171 in pytest_runtest_setup
    [...]
    File ".../pytest/src/_pytest/runner.py", line 115 in pytest_runtest_protocol
    [...]
    File ".../pytest/src/_pytest/main.py", line 317 in pytest_cmdline_main
    [...]

Introduced by this change in pytest, which now deletes the temporary
directory after the test by default:

pytest-dev/pytest#10517

It sounds like something odd like the directory removal causing (Py)Qt
to call the lambda, but the underlying Python object already being gone
or something along those lines. With a proper Qt slot (@pyqtSlot),
PyQt seems to do the right thing, so let's just use that instead...
toofar added a commit that referenced this issue Oct 27, 2023
It all just works!

Changes from the `__main__` implementation down below:

* copy the whole resources directory instead of just the one file:
  looking at the implementation around QTWEBENGINE_RESOURCES_PATH it
  uses the main resources file to find the one directory and then loads
  the other resources from that dir. So I'm assuming it was crashing
  because it couldn't find the other resources. Stack trace was:

    #1  0x00007fffe95f1dca in content::ContentMainRunnerImpl::Initialize(content::ContentMainParams) ()
       from /usr/local/Qt-6.6.0/lib/libQt6WebEngineCore.so.6
    #2  0x00007fffe628cf09 in QtWebEngineCore::WebEngineContext::WebEngineContext() ()
       from /usr/local/Qt-6.6.0/lib/libQt6WebEngineCore.so.6
    #3  0x00007fffe628dfa4 in QtWebEngineCore::WebEngineContext::current() ()
       from /usr/local/Qt-6.6.0/lib/libQt6WebEngineCore.so.6
    #4  0x00000210b845c780 in ?? ()
    #5  0x00000210b845c780 in ?? ()
    #6  0x00007fffffffd480 in ?? ()
    #7  0x00007fffe62391bb in QtWebEngineCore::ProfileAdapter::ProfileAdapter(QString const&) ()
       from /usr/local/Qt-6.6.0/lib/libQt6WebEngineCore.so.6

* write stuff to our cache dir, not tmp ;)

I haven't actually checked this fixes an affected version of Qt (need to
rebuild or get from riverbank pypi). But I unpacked the pak file and it
has the right fake URL in it.
The-Compiler added a commit that referenced this issue Dec 7, 2023
Almost 7 years ago, it was observed that hiding the status bar causes some
websites being scrolled to the top: #2236.

Back then, it never really was clear why this happens. However, with the v3.0.0
release, we had a regression causing the same thing to happen when leaving
prompt mode: #7885.

Thanks to "git bisect", the culprit was found to be 8e152aa, "Don't give
keyboard focus to tab bar", which was a fix for #7820. However, it still wasn't
clear why this phenomenon happens.

What made things clearer to me was a combination of debugging and an old comment
by pevu: #2236 (comment)

    Chromium-browser has the same issue. When you open lipsum.com, scroll down,
    then focus the location bar (url box), then press Tab, it will jump to the
    top of the page and focus the first link. This doesn't happen when you
    switch focus using the mouse.

    It seems to be an issue of how the view containing the website is focused
    when all qutebrowser ui elements disappear.

And indeed, tabbing into the web contents from the UI elements via the tab key
in Chromium causes the website to start at the top, presumably as an
accessibility feature?

Essentially, this is also what happens in qutebrowser when an UI element is
hidden while it still has focus: In QWidget::hide() (or, rather,
QWidgetPrivate::hide_helper()), Qt moves the focus to the next widget by
calling focusPrevNextChild(true):
https://github.com/qt/qtbase/blob/v6.6.1/src/widgets/kernel/qwidget.cpp#L8259-L8271

And apparently, focusPrevNextChild() basically does the same thing as pressing
the tab key, to the point that there is some code in Qt Declarative actually
making tab keypresses out of it (which I'm still not sure is related, or maybe
just the cause of #4579):
https://github.com/qt/qtdeclarative/blob/v6.6.1/src/quickwidgets/qquickwidget.cpp#L1415-L1429

jome debugging confirms that this is exactly what happening:

1) We hide the status bar (or prompt) which has keyboard focus
2) Qt focuses the web view, which triggers the Chromium feature (?) scrolling it
   to the very top.
3) Only then, in TabbedBrowser.on_mod_left(), we noticed that the command or
   prompt mode was left, and reassign focus to the web view properly.

In step 2), before this change, Qt happened to focus the tab bar (before we set
the focus manually to the web contents), and thus this didn't happen.
Not sure why it didn't focus the tab bar when we hid the status bar (maybe
because how our widget hierarchy works with TabbedBrowser?).

Python stacktrace of hiding prompt:

    Traceback (most recent call first):
    <built-in method hide of DownloadFilenamePrompt object at remote 0x7fffb8bc65f0>
    File ".../qutebrowser/mainwindow/prompt.py", line 204, in _on_mode_left
        self.show_prompts.emit(None)
    File ".../qutebrowser/keyinput/modeman.py", line 434, in leave
        self.left.emit(mode, self.mode, self._win_id)
    File ".../qutebrowser/keyinput/modeman.py", line 445, in mode_leave
        self.leave(self.mode, 'leave current')

C++ stacktrace, with the focus change presumably being passed of to Chromium
here: https://github.com/qt/qtwebengine/blob/dev/src/core/render_widget_host_view_qt_delegate_client.cpp#L714

    #0  QtWebEngineCore::RenderWidgetHostViewQtDelegateClient::handleFocusEvent(QFocusEvent*) () at /usr/src/debug/qt6-webengine/qtwebengine-everywhere-src-6.6.0/src/core/render_widget_host_view_qt_delegate_client.cpp:708
    #1  QtWebEngineCore::RenderWidgetHostViewQtDelegateClient::handleFocusEvent(QFocusEvent*) () at /usr/src/debug/qt6-webengine/qtwebengine-everywhere-src-6.6.0/src/core/render_widget_host_view_qt_delegate_client.cpp:705
    #2  0x00007fffe5fea70c in QtWebEngineCore::RenderWidgetHostViewQtDelegateClient::forwardEvent(QEvent*) () at /usr/src/debug/qt6-webengine/qtwebengine-everywhere-src-6.6.0/src/core/render_widget_host_view_qt_delegate_client.cpp:300
    #3  0x00007fffe4dd5c79 in QQuickItem::event(QEvent*) (this=0x555556b6cd20, ev=0x7fffffffa320) at /usr/src/debug/qt6-declarative/qtdeclarative-everywhere-src-6.6.0/src/quick/items/qquickitem.cpp:8871
    #4  0x00007ffff1f7318b in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=<optimized out>, receiver=0x555556b6cd20, e=0x7fffffffa320)
        at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qapplication.cpp:3290
    #5  0x00007ffff295e4a7 in  () at /usr/lib/python3.11/site-packages/PyQt6/QtWidgets.abi3.so
    #6  0x00007ffff59626d8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x555556b6cd20, event=0x7fffffffa320) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/corelib/kernel/qcoreapplication.cpp:1118
    #7  0x00007ffff596271d in QCoreApplication::sendEvent(QObject*, QEvent*) (receiver=<optimized out>, event=<optimized out>) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/corelib/kernel/qcoreapplication.cpp:1536
    #8  0x00007fffe4f33f15 in QQuickDeliveryAgentPrivate::setFocusInScope(QQuickItem*, QQuickItem*, Qt::FocusReason, QFlags<QQuickDeliveryAgentPrivate::FocusOption>)
        (this=<optimized out>, scope=<optimized out>, item=<optimized out>, reason=<optimized out>, options=...) at /usr/src/debug/qt6-declarative/qtdeclarative-everywhere-src-6.6.0/src/quick/util/qquickdeliveryagent.cpp:439
    #9  0x00007fffe4dd348a in QQuickItem::setFocus(bool, Qt::FocusReason) (this=0x555556b724d0, focus=<optimized out>, reason=Qt::TabFocusReason) at /usr/include/qt6/QtCore/qflags.h:73
    #10 0x00007fffe4e7239b in QQuickWindow::focusInEvent(QFocusEvent*) (this=<optimized out>, ev=<optimized out>) at /usr/src/debug/qt6-declarative/qtdeclarative-everywhere-src-6.6.0/src/quick/items/qquickwindow.cpp:231
    #11 0x00007ffff1fc3a05 in QWidget::event(QEvent*) (this=0x555556457b50, event=0x7fffffffa770) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qwidget.cpp:9111
    #12 0x00007ffff1f7318b in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=<optimized out>, receiver=0x555556457b50, e=0x7fffffffa770)
        at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qapplication.cpp:3290
    #13 0x00007ffff295e4a7 in  () at /usr/lib/python3.11/site-packages/PyQt6/QtWidgets.abi3.so
    #14 0x00007ffff59626d8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x555556457b50, event=0x7fffffffa770) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/corelib/kernel/qcoreapplication.cpp:1118
    #15 0x00007ffff596271d in QCoreApplication::sendEvent(QObject*, QEvent*) (receiver=<optimized out>, event=<optimized out>) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/corelib/kernel/qcoreapplication.cpp:1536
    #16 0x00007ffff1f7f1b2 in QApplicationPrivate::setFocusWidget(QWidget*, Qt::FocusReason) (focus=0x555556457b50, reason=<optimized out>) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qapplication.cpp:1538
    #17 0x00007ffff1fca29d in QWidget::setFocus(Qt::FocusReason) (this=0x555556b1ceb0, reason=<optimized out>) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qwidget.cpp:6580
    #18 0x00007ffff1fb4f1b in QWidget::focusNextPrevChild(bool) (this=<optimized out>, next=<optimized out>) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qwidget.cpp:6844
    #19 0x00007ffff298d0ac in  () at /usr/lib/python3.11/site-packages/PyQt6/QtWidgets.abi3.so
    #20 0x00007ffff298d0ac in  () at /usr/lib/python3.11/site-packages/PyQt6/QtWidgets.abi3.so
    #21 0x00007ffff298d0ac in  () at /usr/lib/python3.11/site-packages/PyQt6/QtWidgets.abi3.so
    #22 0x00007ffff1fbdb76 in QWidgetPrivate::hide_helper() (this=this@entry=0x55555646a360) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qwidget.cpp:8271
    #23 0x00007ffff1fbf158 in QWidgetPrivate::setVisible(bool) (this=0x55555646a360, visible=<optimized out>) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qwidget.cpp:8447
    [...]

We fix this problem by explicitly handling focus before hiding the UI elements.
This is done with a new TabbedBrowser.on_release_focus() slot, which is bound to
signals emitted just before things are hidden: The existing Command.hide_cmd()
for the status bar, and a new release_focus() signal for prompts.

Additionally, we make sure to not double-handle hiding in the statusbar
code when it's already handled separately for comamnd mode.

Unfortunately, no tests for this, as application window focus is required to
reproduce the issue. In theory, a test in scroll.feature could be added though,
which loads simple.html, scrolls down, shows/hides a prompt or the status bar,
and then checks the vertical scroll position is != 0.

Fixes #2236
Fixes #7885
The-Compiler added a commit that referenced this issue Dec 7, 2023
Almost 7 years ago, it was observed that hiding the status bar causes some
websites being scrolled to the top: #2236.

Back then, it never really was clear why this happens. However, with the v3.0.0
release, we had a regression causing the same thing to happen when leaving
prompt mode: #7885.

Thanks to "git bisect", the culprit was found to be 8e152aa, "Don't give
keyboard focus to tab bar", which was a fix for #7820. However, it still wasn't
clear why this phenomenon happens.

What made things clearer to me was a combination of debugging and an old comment
by pevu: #2236 (comment)

> Chromium-browser has the same issue. When you open lipsum.com, scroll down,
> then focus the location bar (url box), then press Tab, it will jump to the
> top of the page and focus the first link. This doesn't happen when you
> switch focus using the mouse.
>
> It seems to be an issue of how the view containing the website is focused
> when all qutebrowser ui elements disappear.

And indeed, tabbing into the web contents from the UI elements via the tab key
in Chromium causes the website to start at the top, presumably as an
accessibility feature?

Essentially, this is also what happens in qutebrowser when an UI element is
hidden while it still has focus: In QWidget::hide() (or, rather,
QWidgetPrivate::hide_helper()), Qt moves the focus to the next widget by
calling focusPrevNextChild(true):
https://github.com/qt/qtbase/blob/v6.6.1/src/widgets/kernel/qwidget.cpp#L8259-L8271

And apparently, focusPrevNextChild() basically does the same thing as pressing
the tab key, to the point that there is some code in Qt Declarative actually
making tab keypresses out of it (which I'm still not sure is related, or maybe
just the cause of #4579):
https://github.com/qt/qtdeclarative/blob/v6.6.1/src/quickwidgets/qquickwidget.cpp#L1415-L1429

Some debugging confirms that this is exactly what happening:

1) We hide the status bar (or prompt) which has keyboard focus
2) Qt focuses the web view, which triggers the Chromium feature (?) scrolling it
   to the very top.
3) Only then, in TabbedBrowser.on_mod_left(), we noticed that the command or
   prompt mode was left, and reassign focus to the web view properly.

In step 2), before this change, Qt happened to focus the tab bar (before we set
the focus manually to the web contents), and thus this didn't happen.
Not sure why it didn't focus the tab bar when we hid the status bar (maybe
because how our widget hierarchy works with TabbedBrowser?).

Python stacktrace of hiding prompt:

    Traceback (most recent call first):
    <built-in method hide of DownloadFilenamePrompt object at remote 0x7fffb8bc65f0>
    File ".../qutebrowser/mainwindow/prompt.py", line 204, in _on_mode_left
        self.show_prompts.emit(None)
    File ".../qutebrowser/keyinput/modeman.py", line 434, in leave
        self.left.emit(mode, self.mode, self._win_id)
    File ".../qutebrowser/keyinput/modeman.py", line 445, in mode_leave
        self.leave(self.mode, 'leave current')

C++ stacktrace, with the focus change presumably being passed of to Chromium
here: https://github.com/qt/qtwebengine/blob/dev/src/core/render_widget_host_view_qt_delegate_client.cpp#L714

    #0  QtWebEngineCore::RenderWidgetHostViewQtDelegateClient::handleFocusEvent(QFocusEvent*) () at /usr/src/debug/qt6-webengine/qtwebengine-everywhere-src-6.6.0/src/core/render_widget_host_view_qt_delegate_client.cpp:708
    #1  QtWebEngineCore::RenderWidgetHostViewQtDelegateClient::handleFocusEvent(QFocusEvent*) () at /usr/src/debug/qt6-webengine/qtwebengine-everywhere-src-6.6.0/src/core/render_widget_host_view_qt_delegate_client.cpp:705
    #2  0x00007fffe5fea70c in QtWebEngineCore::RenderWidgetHostViewQtDelegateClient::forwardEvent(QEvent*) () at /usr/src/debug/qt6-webengine/qtwebengine-everywhere-src-6.6.0/src/core/render_widget_host_view_qt_delegate_client.cpp:300
    #3  0x00007fffe4dd5c79 in QQuickItem::event(QEvent*) (this=0x555556b6cd20, ev=0x7fffffffa320) at /usr/src/debug/qt6-declarative/qtdeclarative-everywhere-src-6.6.0/src/quick/items/qquickitem.cpp:8871
    #4  0x00007ffff1f7318b in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=<optimized out>, receiver=0x555556b6cd20, e=0x7fffffffa320)
        at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qapplication.cpp:3290
    #5  0x00007ffff295e4a7 in  () at /usr/lib/python3.11/site-packages/PyQt6/QtWidgets.abi3.so
    #6  0x00007ffff59626d8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x555556b6cd20, event=0x7fffffffa320) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/corelib/kernel/qcoreapplication.cpp:1118
    #7  0x00007ffff596271d in QCoreApplication::sendEvent(QObject*, QEvent*) (receiver=<optimized out>, event=<optimized out>) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/corelib/kernel/qcoreapplication.cpp:1536
    #8  0x00007fffe4f33f15 in QQuickDeliveryAgentPrivate::setFocusInScope(QQuickItem*, QQuickItem*, Qt::FocusReason, QFlags<QQuickDeliveryAgentPrivate::FocusOption>)
        (this=<optimized out>, scope=<optimized out>, item=<optimized out>, reason=<optimized out>, options=...) at /usr/src/debug/qt6-declarative/qtdeclarative-everywhere-src-6.6.0/src/quick/util/qquickdeliveryagent.cpp:439
    #9  0x00007fffe4dd348a in QQuickItem::setFocus(bool, Qt::FocusReason) (this=0x555556b724d0, focus=<optimized out>, reason=Qt::TabFocusReason) at /usr/include/qt6/QtCore/qflags.h:73
    #10 0x00007fffe4e7239b in QQuickWindow::focusInEvent(QFocusEvent*) (this=<optimized out>, ev=<optimized out>) at /usr/src/debug/qt6-declarative/qtdeclarative-everywhere-src-6.6.0/src/quick/items/qquickwindow.cpp:231
    #11 0x00007ffff1fc3a05 in QWidget::event(QEvent*) (this=0x555556457b50, event=0x7fffffffa770) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qwidget.cpp:9111
    #12 0x00007ffff1f7318b in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=<optimized out>, receiver=0x555556457b50, e=0x7fffffffa770)
        at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qapplication.cpp:3290
    #13 0x00007ffff295e4a7 in  () at /usr/lib/python3.11/site-packages/PyQt6/QtWidgets.abi3.so
    #14 0x00007ffff59626d8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x555556457b50, event=0x7fffffffa770) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/corelib/kernel/qcoreapplication.cpp:1118
    #15 0x00007ffff596271d in QCoreApplication::sendEvent(QObject*, QEvent*) (receiver=<optimized out>, event=<optimized out>) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/corelib/kernel/qcoreapplication.cpp:1536
    #16 0x00007ffff1f7f1b2 in QApplicationPrivate::setFocusWidget(QWidget*, Qt::FocusReason) (focus=0x555556457b50, reason=<optimized out>) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qapplication.cpp:1538
    #17 0x00007ffff1fca29d in QWidget::setFocus(Qt::FocusReason) (this=0x555556b1ceb0, reason=<optimized out>) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qwidget.cpp:6580
    #18 0x00007ffff1fb4f1b in QWidget::focusNextPrevChild(bool) (this=<optimized out>, next=<optimized out>) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qwidget.cpp:6844
    #19 0x00007ffff298d0ac in  () at /usr/lib/python3.11/site-packages/PyQt6/QtWidgets.abi3.so
    #20 0x00007ffff298d0ac in  () at /usr/lib/python3.11/site-packages/PyQt6/QtWidgets.abi3.so
    #21 0x00007ffff298d0ac in  () at /usr/lib/python3.11/site-packages/PyQt6/QtWidgets.abi3.so
    #22 0x00007ffff1fbdb76 in QWidgetPrivate::hide_helper() (this=this@entry=0x55555646a360) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qwidget.cpp:8271
    #23 0x00007ffff1fbf158 in QWidgetPrivate::setVisible(bool) (this=0x55555646a360, visible=<optimized out>) at /usr/src/debug/qt6-base/qtbase-everywhere-src-6.6.0/src/widgets/kernel/qwidget.cpp:8447
    [...]

We fix this problem by explicitly handling focus before hiding the UI elements.
This is done with a new TabbedBrowser.on_release_focus() slot, which is bound to
signals emitted just before things are hidden: The existing Command.hide_cmd()
for the status bar, and a new release_focus() signal for prompts.

Additionally, we make sure to not double-handle hiding in the statusbar
code when it's already handled separately for comamnd mode.

Unfortunately, no tests for this, as application window focus is required to
reproduce the issue. In theory, a test in scroll.feature could be added though,
which loads simple.html, scrolls down, shows/hides a prompt or the status bar,
and then checks the vertical scroll position is != 0.

Fixes #2236
Fixes #7885
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants