Skip to content

Fix crash on exit when closing multiple profiles#8203

Merged
vadi2 merged 20 commits intoMudlet:developmentfrom
Excellencedev:fix-7478
Oct 11, 2025
Merged

Fix crash on exit when closing multiple profiles#8203
vadi2 merged 20 commits intoMudlet:developmentfrom
Excellencedev:fix-7478

Conversation

@Excellencedev
Copy link
Copy Markdown
Contributor

@Excellencedev Excellencedev commented Sep 10, 2025

/claim #7478
/closes #7478

Description:

This PR resolves a crash that occurs when closing multiple profiles simultaneously.

The root cause was a race condition in the Host destructor, where weak pointers to command line objects (mActiveCommandLines) were being accessed after they were no longer valid.

The fix involves explicitly clearing the mActiveCommandLines container at the beginning of the Host destructor. This ensures that the resources are released in a safe order, preventing the crash.

Here is the correct screencast @vadi2 : https://github.com/user-attachments/assets/49c0c926-1e97-4000-aceb-f47511e6ab51

@Excellencedev
Copy link
Copy Markdown
Contributor Author

Excellencedev commented Sep 10, 2025

Please review this PR ad let me know what you think by dropping a comment @vadi2 @ZookaOnGit @Kebap
Also please consider reviewing this one when you have time #8174

@Excellencedev
Copy link
Copy Markdown
Contributor Author

Closed it by mistake

@Excellencedev Excellencedev mentioned this pull request Sep 13, 2025
@vadi2 vadi2 self-assigned this Sep 13, 2025
@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Sep 13, 2025

@Excellencedev please provide a screencast where this is shown to work, thank you:

image

@Excellencedev
Copy link
Copy Markdown
Contributor Author

Will do so

@Excellencedev
Copy link
Copy Markdown
Contributor Author

@vadi2 Here is the screencast: https://github.com/user-attachments/assets/526aa1eb-e246-4977-ba49-d4fbc34483d7

I opened 16 profiles on Mudlet, and closed them quickly with Alt + W and there was no crash

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Sep 16, 2025

The screencast doesn't seem to show profiles being closed at all, did you attach the right video?

@Excellencedev
Copy link
Copy Markdown
Contributor Author

@vadi2 I am sorry for the mistake. I posted the wrong video

@Excellencedev
Copy link
Copy Markdown
Contributor Author

@Excellencedev
Copy link
Copy Markdown
Contributor Author

Hello @vadi2, have you checked the new screencast: https://github.com/user-attachments/assets/49c0c926-1e97-4000-aceb-f47511e6ab51 and what do you think

@Excellencedev
Copy link
Copy Markdown
Contributor Author

Hello @vadi2 , I sent a new screencast

@Excellencedev
Copy link
Copy Markdown
Contributor Author

It's been a week. Hello @vadi2
I have updates on this PR. Please comment

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Sep 24, 2025

Still crashes unfortunately when I run the test described. Here is one stacktrace (now different from what was there before):

Thread 1 "mudlet" received signal SIGSEGV, Segmentation fault.
0x000055555602a9ee in Tree<TKey>::isActive() const ()
(gdb) 
(gdb) 
(gdb) bt
#0  0x000055555602a9ee in Tree<TKey>::isActive() const ()
#1  0x00005555562cd83a in TKey::match(Qt::Key, QFlags<Qt::KeyboardModifier>, bool) ()
#2  0x00005555560bf409 in KeyUnit::processDataStream(Qt::Key, QFlags<Qt::KeyboardModifier>) ()
#3  0x000055555625cf96 in TCommandLine::keybindingMatched(QKeyEvent*) ()
#4  0x000055555625e413 in TCommandLine::event(QEvent*) ()
#5  0x00007ffff6b9197b in QApplicationPrivate::notify_helper(QObject*, QEvent*)
    () from /home/vadi/squashfs-root/lib/libQt6Widgets.so.6
#6  0x00007ffff6b9ab2b in QApplication::notify(QObject*, QEvent*) ()
   from /home/vadi/squashfs-root/lib/libQt6Widgets.so.6
#7  0x00007ffff737ff9a in QCoreApplication::notifyInternal2(QObject*, QEvent*)
    () from /home/vadi/squashfs-root/lib/libQt6Core.so.6
#8  0x00007ffff6c09b93 in ?? ()
   from /home/vadi/squashfs-root/lib/libQt6Widgets.so.6
#9  0x00007ffff6b9197b in QApplicationPrivate::notify_helper(QObject*, QEvent*)
    () from /home/vadi/squashfs-root/lib/libQt6Widgets.so.6
#10 0x00007ffff737ff9a in QCoreApplication::notifyInternal2(QObject*, QEvent*)
    () from /home/vadi/squashfs-root/lib/libQt6Core.so.6
#11 0x00007ffff5fea363 in QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent*) () from /home/vadi/squashfs-root/lib/libQt6Gui.so.6
#12 0x00007ffff19c431b in ?? ()
   from /home/vadi/squashfs-root/plugins/platforminputcontexts/libibusplatformin--Type <RET> for more, q to quit, c to continue without paging--

What OS are you testing this on?

@Excellencedev
Copy link
Copy Markdown
Contributor Author

Excellencedev commented Sep 25, 2025

What OS are you testing this on?

Windows

@Excellencedev
Copy link
Copy Markdown
Contributor Author

Excellencedev commented Sep 25, 2025

@vadi2 I might have fixed it now

The 1st fix from before (mpLastCommandLineUsed.clear()) worked because Qt on Windows doesn’t deliver events during destruction. On Linux, however, Qt continues processing pending events, which caused the crash.

The stacktrace confirms this: a QKeyEvent was still delivered to TCommandLine::keybindingMatched(), which called into KeyUnit/Tree objects that had already been destroyed → classic use-after-free.

The new commit adds a guard in TCommandLine::keybindingMatched() to skip processing when the host is shutting down, making the fix robust across platforms.

Crash site:

#0 Tree::isActive() const

→ This is being called from inside TKey::match(). That means something is calling into a keybinding structure that’s already been torn down. Classic use-after-free.

Call path:

TCommandLine::keybindingMatched(QKeyEvent*)
→ KeyUnit::processDataStream()
→ TKey::match()
→ Tree::isActive()

→ This shows a QKeyEvent being delivered to TCommandLine while destruction is already happening.

Qt event loop evidence:

QApplicationPrivate::notify_helper
QApplication::notify
QCoreApplication::notifyInternal2
QGuiApplicationPrivate::processKeyEvent

→ Confirms that Qt’s event system was still dispatching key events after the underlying structures were already being destroyed.

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Sep 25, 2025

Using the latest commit, the stacktrace looks the same:

Thread 1 "mudlet" received signal SIGSEGV, Segmentation fault.
0x000055555602e27c in Tree<TKey>::isActive() const ()
(gdb) bt
#0  0x000055555602e27c in Tree<TKey>::isActive() const ()
#1  0x00005555562d3d7e in TKey::match(Qt::Key, QFlags<Qt::KeyboardModifier>, bool) ()
#2  0x00005555560c2e95 in KeyUnit::processDataStream(Qt::Key, QFlags<Qt::KeyboardModifier>) ()
#3  0x0000555556262fba in TCommandLine::keybindingMatched(QKeyEvent*) ()
#4  0x0000555556264471 in TCommandLine::event(QEvent*) ()
#5  0x00007ffff6b9197b in QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Widgets.so.6
#6  0x00007ffff6b9ab2b in QApplication::notify(QObject*, QEvent*) ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Widgets.so.6
#7  0x00007ffff737ff9a in QCoreApplication::notifyInternal2(QObject*, QEvent*) ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Core.so.6
#8  0x00007ffff6c09b93 in ?? () from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Widgets.so.6
#9  0x00007ffff6b9197b in QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Widgets.so.6
#10 0x00007ffff737ff9a in QCoreApplication::notifyInternal2(QObject*, QEvent*) ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Core.so.6
#11 0x00007ffff5fea363 in QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent*) ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Gui.so.6
#12 0x00007ffff19c431b in ?? ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/plugins/platforminputcontexts/libibusplatforminputcontextplugin.so
#13 0x00007ffff73e3d38 in ?? () from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Core.so.6
#14 0x00007ffff59c36b3 in QDBusPendingCallWatcher::finished(QDBusPendingCallWatcher*) ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6DBus.so.6
#15 0x00007ffff73d7fd8 in QObject::event(QEvent*) ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Core.so.6
#16 0x00007ffff6b9197b in QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Widgets.so.6
#17 0x00007ffff737ff9a in QCoreApplication::notifyInternal2(QObject*, QEvent*) ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Core.so.6
#18 0x00007ffff738372d in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Core.so.6
#19 0x00007ffff76667e7 in ?? () from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Core.so.6
#20 0x00007ffff5510d3b in g_main_context_dispatch ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libglib-2.0.so.0
#21 0x00007ffff55662b8 in ?? () from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libglib-2.0.so.0
#22 0x00007ffff550e3e3 in g_main_context_iteration ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libglib-2.0.so.0
#23 0x00007ffff7665e9e in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Core.so.6
#24 0x00007ffff738cd0b in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Core.so.6
#25 0x00007ffff7388c9a in QCoreApplication::exec() ()
   from /home/vadi/Downloads/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64/Mudlet-4.19.1-testing-pr8203-27b0f87e-linux-x64.AppImage/squashfs-root/lib/libQt6Core.so.6
#26 0x00005555560f2708 in main ()
(gdb) 

Try installing Linux in Virtualbox, both are free, and you'll be able to see the same result there.

@Excellencedev
Copy link
Copy Markdown
Contributor Author

I think it is fixed rn
Please try to do it and see if it crashes with the new latest commit @vadi2
Test it please

@Excellencedev
Copy link
Copy Markdown
Contributor Author

Hello @vadi2 ?

Copy link
Copy Markdown
Member

@vadi2 vadi2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! No crashes now. But it adds C++ exceptions, which you might notice we don't use in the codebase. Try fixing the issue without adding them.

@Excellencedev
Copy link
Copy Markdown
Contributor Author

I will do that @vadi2. Thanks for review

…tdown by replacing the `try-catch` block with checks for `keyObject->isActive()` and `keyObject->mpHost->isClosingDown()`.

Modified `src/TCommandLine.cpp` to remove exception handling and added null checks for `mpHost` to prevent crashes during profile shutdown.
@Excellencedev
Copy link
Copy Markdown
Contributor Author

@vadi2 I have removed the try catch blocks. it still does not crash

@Excellencedev Excellencedev requested a review from vadi2 October 10, 2025 19:16
@Excellencedev
Copy link
Copy Markdown
Contributor Author

@vadi2 I have removed the try catch blocks. it still does not crash. Hello ?

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Oct 11, 2025

This is a volunteer project that we work on at our free time, don't spam us please.

@Excellencedev
Copy link
Copy Markdown
Contributor Author

This is a volunteer project that we work on at our free time, don't spam us please.

@vadi2 So sorry

Copy link
Copy Markdown
Member

@vadi2 vadi2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We got there in the end!

@vadi2 vadi2 merged commit cefdaea into Mudlet:development Oct 11, 2025
12 checks passed
@Excellencedev
Copy link
Copy Markdown
Contributor Author

@vadi2 Thanks

@Excellencedev Excellencedev deleted the fix-7478 branch October 11, 2025 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crash on Mudlet exit when closing multiple profiles at once

2 participants