Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Qt::Popup window in debugger seizes up whole windowing system



  • I asked this question a long time ago, but never got an answer. I am trying again. I really would appreciate some answers/help here this time, please....

    If I have a Qt::Popup window visible while debugging and code hits a breakpoint, assert or any error which will cause the debugger to take control, the popup remains on-screen and my whole desktop windowing system seizes up, with nothing I can do about it!! :(

    I am Linux/Ubuntu with GNOME desktop. (In a Windows VirtualBox, but that should not be relevant.) Everything is vanilla. Has happened with every Qt Creator/Qt/OS release since I started years ago. This may (well?) not happen on Windows, or even MacOS, I do not know.

    I cannot show a screenshot, because once it happens I cannot do anything, I cannot click, type a character, close either the app or stop the debugger, abort, kill, run another application, click to another window, nothing! I either have to hard-kill-reboot the machine, or use Ctrl+Alt+F3 to get to re-log in in a terminal window, pkill the paused application or the gdb, then Ctrl+Alt+F1 to get back to re-log into the desktop, and then I can use my system. Though of course by now I can't continue in the debugger for the fault, but it's a bit better than rebooting the whole VM!

    This is a show-stopper. It makes debugging difficult to say the least, worse I spend my life fearing that some unrelated piece of code elsewhere which happens to be called from the slot will cause a debugger break, and then I will get locked up.

    I paste an absolute minimal repro below:

    #include <QApplication>
    #include <QDebug>
    #include <QPushButton>
    #include <QVBoxLayout>
    #include <QWidget>
    
    class AWidget : public QWidget
    {
    private:
        QPushButton *_btn, *_btn2;
        QWidget *_popup;
    
    public:
        explicit AWidget(QWidget *parent = nullptr) :
            QWidget(parent)
        {
            setGeometry(100, 100, 200, 200);
            setLayout(new QVBoxLayout);
    
            // create a `Qt::Popup` widget
            _popup = new QWidget(this);
            _popup->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint);
            _popup->setGeometry(300, 300, 200, 200);
            _popup->setLayout(new QVBoxLayout);
            // put a button on popup widget, connect button's click to the test slot
            // so the slot will be called while the popup is up-front
            _btn2 = new QPushButton("Click to invoke slot");
            _popup->layout()->addWidget(_btn2);
            connect(_btn2, &QPushButton::clicked, this, &AWidget::aSlot);
    
            // put a button on this widget, connect button's click to show the popup widget
            _btn = new QPushButton("Click to open popup");
            layout()->addWidget(_btn);
            connect(_btn, &QPushButton::clicked, _popup, &QWidget::show);
        }
    
    private slots:
        void aSlot()
        {
            // the slot called while a popup is up-front
            // disaster strikes if you have a breakpoint/assert/error here, *or in anything this calls*
            // because the popup stays up-front "blocks" everything in the windowing system when in the debugger
            qDebug() << "aSlot";
    //        Q_ASSERT(false);
        }
    };
    
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        AWidget w;
    
        w.show();
        return a.exec();
    }
    

    As it stands it will work OK. Now put a breakpoint in aSlot(), or uncomment the Q_ASSERT(false) there. Be prepared for lock-up....

    It is true that if you introduce _popup->hide() as the very first line in the slot, then at least you do not get seized up. However, that stops me using the popup in the normal way, and I'd have to have it there permanently while debugging for every popup/slot just in case a code error elsewhere happened to get hit, which is obviously not practical.

    I am looking for:

    • Someone to test this under Linux/GNOME/whatever to confirm they have the problem, it's not just me.
    • (I don't mind if someone tests behaviour under Windows, but even if it works there that will not help me.)
    • I want either to be told how to "fix" the lock-up behaviour if that can be done, or...
    • ...to be told how I can have any kind of reasonable debugging experience, what exactly do you do if you need Popup windows in your application and need to debug?

    I should really appreciate some answers from the experts, kindly please. The code to paste is really simple. I am currently in a situation where the app has to have a Popup and I have to be able to debug, and I'm in trouble... :(


  • Lifetime Qt Champion

    Hi,

    I do not have a direct answer for that but maybe some ideas to help you find what is going wrong.

    Since you can reproduce that in a virtual machine, can you screenshot the virtual machine screen from the host ? That might allow to see something there.

    Also, one thing you can do is to ssh into your virtual machine so you can check live what goes on when hitting that break point. Unless the whole machine freezes, you should be able to run tools like top, dmesg (with the help of tail) and their friends. You should even be able to restart the desktop environment from there.

    One other thing, which Ubuntu variants are you currently running ? There are several of them so a precise version number might help.
    Qt Creator and gdb versions will also be a good thing to have.



  • @SGaist
    I will shortly get back to you on all this. But I know what is happening. It is quite simply: there is a modal pop-up window visible on the desktop, when the debugger breakpoint is hit. The program cannot continue because it has broken into the debugger. And no other desktop window, neither the debugger nor anything else unrelated, can be clicked to/typed into because of the modal popup being there. That is precisely what the issue is.

    Everything is "working" as it should. the app is paused, the debugger has been broken into at the right place, the desktop is still running, and so on. The problem is solely that because of the modal, up-front popup you cannot interact with anything on the desktop!

    I used to have a similar-ish problem years ago developing under Windows (not Qt), whenever a combobox was dropped down and a break was hit. The combo's "choices" is a kind of modal, popup window, and same thing used to happen: locked up-front on the desktop, cannot get rid of it, cannot access anything else at all on desktop, reboot the PC. At some point either Windows behaviour or VS debugger changed to handle it, thankfully --- or maybe it never did! I tried a QCombobox for same problem here, to my surprise that does work OK when break (dropdown gets dismissed or whatever), but not for Qt::Popup....

    Are you Linux? I think actually you are macOS? Could you just tell me what happens to you if you try this short code with a breakpoint/assert in your environment, do you seize up or not?


  • Lifetime Qt Champion

    So you may found something, using a remote session and having only started Qt Creator 4.13.3 it does indeed block all interactions once the "Signal Received" dialog appears.

    I have not found anything suspicious in the logs. However, one thing I could observe is that there seems to be two dialogs appearing in quick succession but I could not see the first one, only the "Signal Received".

    @JonB said in Qt::Popup window in debugger seizes up whole windowing system:

    Are you Linux? I think actually you are macOS? Could you just tell me what happens to you if you try this short code with a breakpoint/assert in your environment, do you seize up or not?

    I have worked with/on Qt on many platforms and even embedded ones when cross-compilation was not yet the thing it is nowadays :-)



  • @SGaist
    Here is a screenshot of the VM taken from the Windows host:
    VirtualBox_Ubuntu 20.04_09_12_2020_13_02_23.png

    You can even see where it has hit the breakpoint in the debugger, and the output of aSlot message in Application Output from previous line. If you were in front of it, you can even see the line cursor flashing on the source line it is on. Nothing on the machine has actually "seized up/crashed", it's all just as it should be. The problem is that Popup window with Click to invoked slot on it. That is a modal, up-front window, and it is because of this that you cannot interact with anything, anywhere on the desktop.

    When I Ctrl+Alt+F1 to get a new login window from the VM (effectively the same as your ssh), and do my ps es, it's as it should be, for the app and for gdb and for Creator. If I pkill -9 theApp, or kill the gdb, or kill the Creator, then when I'm done and go back to the desktop via Ctrl+Alt+F3 the desktop has regained normal control, because the necessary process was killed.

    If I put _popup->hide() on the line above the breakpoint, that popup window goes away when the break is hit and all is well. But that's not a solution for debugging, a breakpoint could be anywhere in code....

    I am Ubuntu 20.04, GNOME desktop, gcc 9.3.0, gdb 9.2, Creator 4.11.0, Qt 5.12. However, over the years I have had different versions of all of these and (so far as I do recall) this has always been a problem. I have given up debugging when I have any visible Popup window, which is much of the time in current application, and I am now fed up not being able to debug...! :(

    Either the desktop windowing system has (somehow) to be told to behave differently, or Qt Creator has to know about this and take some action when hitting a breakpoint etc. to "free" the modality and allow the user to continue?


  • Moderators

    @JonB
    thats super odd, the popup shouldn't grab the input from the whole windowing system, but only from your application, which should be a different process to QtCreator!

    Can you upload that basic example ?
    Would love to test it myself



  • @J-Hilk said in Qt::Popup window in debugger seizes up whole windowing system:

    thats super odd, the popup shouldn't grab the input from the whole windowing system, but only from your application, which should be a different process to QtCreator!

    Yeah, well, like I say, similar used to happen under Windows for a combobox's dropdown getting "frozen" on-screen when a break hit, cannot interact with desktop because of that, cannot close it because at a break in the debugger. => Reboot Windows! Did it for years :( But now I'm Linux I want better!

    Can you upload that basic example ?

    ? I pasted the 30-odd lines of code in my first post above, that's all you have to try? Am I not understanding?


  • Moderators

    @JonB said in Qt::Popup window in debugger seizes up whole windowing system:

    I pasted the 30-odd lines of code in my first post above, that's all you have to try? Am I not understanding?

    sorry didn't see it 😔



  • @SGaist , @J-Hilk , @whoever
    We can eliminate the issue from being in a slot on the Popup window. At the end of my AWidget constructor, get rid of the connect() and just show the popup window, followed by a breakpoint/assert/other error:

            // put a button on this widget, connect button's click to show the popup widget
            _btn = new QPushButton("Click to open popup");
            layout()->addWidget(_btn);
    //        connect(_btn, &QPushButton::clicked, _popup, &QWidget::show);
            _popup->show();
            Q_ASSERT(false);
        }
    

    Because the Popup is shown, this "freezes" on the Q_ASSERT() line. You see the popup window on the desktop (though without content visible), and that's enough to exhibit the problem.

    EDIT
    Because of this I can reduce the problem to just the following 5 lines:

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        QWidget popup(nullptr, Qt::Popup);  // the `Qt::Popup` flag is what causes the problem
        popup.show();
        Q_ASSERT(false);
    
        return a.exec();
    }
    

    You (I) get to see that a Popup has come up, and the desktop is dead when it hits the Q_ASSERT or you put a breakpoint on that line...



  • This is still on-going...?

    I was really hoping someone would try the 5-liner on Ubuntu, or perhaps any Linux with GNOME, or without? I am seeking to know whether this experience is common?

    I have discovered the same lockup if I run the code from gdb in a terminal instead of from Creator.

    I have discovered that if I change Qt::Popup to Qt::WindowStaysOnTopHint the seizure does not happen. I get the popup behaviour of the window being up-front. If I hit a debugger break, the window does still stay there, on top of Creator. Fair enough. But I can continue interacting with the desktop or the Creator debugger, no problem.

    The problem will be related to do whatever Popup causes to happen after it has just been shown, where any mouse-click --- including elsewhere on the desktop, unrelated to the running app --- or any key press is "eaten" by the Popup window, dismissing itself. Because that never arrives in the debug-break case, the popup window remains up-front and no mouse click/key goes anywhere else.

    Can someone explain what/how Qt::Popup does its next-click-to-dismiss work, especially under X11, or wherever this behaviour occurs?


  • Lifetime Qt Champion

    That's likely something to look in the xcb backend. These flags behave differently depending on the underlying OS as they are mapped to the corresponding platform flags.


Log in to reply