Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-4763

Assert when throwing exception in menu items

    XMLWordPrintable

Details

    • 95e438189a36c71d632099b3873557103697bc3b

    Description

      We noticed a problem in Qt, when you throw an exception from a menu item's slot. Below I have attached the code to reproduce the problem in Qt's "mainwindows/menus" example.

      When you run this code in debug configuration, and choose Help -> About, the application throws an exception (not visible other than in console). Ok, so far no problem. But, then try to choose Help -> About again. When you hover your mouse over About, the assertion happens. This is because the exception interrupted the method activateCausedStack() in qmenu.cpp. This method is not exception-safe, because the activationRecursionGuard boolean is cleared only when this method successfully completes. Any exception will cause the method to not finish, and the problem occurs. Most likely Qt code has similar problems elsewhere.

      A nice fix for this is to create a class which takes care of clearing any boolean flags, when it's destructor is ran. Make an object of this class at the beginning of the method, the constructor setting the boolean to true. Then it will be cleared even if the method is interrupted, because the object is destroyed when the method ends. No matter if it was successful or not.

      Modify Qt's "mainwindows/menus" example as follows:
      main.cpp:

      #include <QApplication>
      #include <exception>
      #include <iostream>

      #include "mainwindow.h"

      class MyQApplication : public QApplication
      {
      public:
      MyQApplication(int &argc, char *argv[]) : QApplication(argc, argv)
      {
      }

      bool notify(QObject *receiver, QEvent *event)
      {
      try
      {
      return QApplication::notify(receiver, event);
      }
      catch(std::exception &e)
      {
      std::cout << e.what() << std::endl;
      }
      }
      };

      int main(int argc, char *argv[])
      {
      MyQApplication app(argc, argv);
      MainWindow window;
      window.show();
      return app.exec();
      }

      MainWindow.cpp:

      // add this include
      #include <exception>

      // throw exception in about()
      void MainWindow::about()
      {
      throw std::range_error("error test");

      infoLabel->setText(tr("Invoked <b>Help|About</b>"));
      QMessageBox::about(this, tr("About Menu"),
      tr("The <b>Menu</b> example shows how to create "
      "menu-bar menus and context menus."));
      }

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            monsen Marius Bugge Monsen
            sthomass Stian Sandvik Thomassen (closed Nokia identity) (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes