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

qt5.2 crash due to accessing destroyed QWidgetWindow

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P3: Somewhat important
    • 5.2.1
    • 5.2.0
    • None
    • Windows 7 x64
      VS2010
    • 8fcab70408628f730860d3861a06fc519d069f5e (14.12.2013)

    Description

      In some circumstances Qt 5.2 will crash due to accessing destroyed QWidgetWindow object. The attched sample program can reproduce this issue, just build it in debug mode and run it, press button named 'Push Me To Crash!' you can see the crash.

      The logic behind the crash is explained below:
      In this sample program, I first created a QSplitter widget 'splitter' without parent widget and add some offspring widgets to it, among them there is a QGLWidget widget 'glW', and then I create a top level widget 'topW' and set its parent to one of the offspring widget of 'splitter' and show the widget 'topW', this will make qt5 call createWinId() to 'topW's ancestor widget 'splitter', in createWinId() of 'splitter' it will call q_createNativeChildrenAndSetParent() to create all native children recursively and finally make 'glW's QWidgetWindow object become the child of 'splitter's QWidgetWindow object. Then I add 'splitter' to a stacked widget and show it, this will make qt5 call setParent_sys() to 'splitter'. According to the code in setParent_sys():

          // Reparenting toplevel to child
          if (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
              if (extra && extra->hasWindowContainer)
                  QWindowContainer::toplevelAboutToBeDestroyed(q);
              q->destroy();
          }
      

      qt5 will call destroy() to 'splitter', in QWidget::destroy() it will first call destroy() to its child widgets recursively:

              if (destroySubWindows) {
                  QObjectList childList(children());
                  for (int i = 0; i < childList.size(); i++) {
                      QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
                      if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
                          if (widget->windowHandle()) {
                              widget->destroy();
                          }
                      }
                  }
              }
      

      Since 'splitter's child widgets (one of them is the parent of 'glW') don't have Qt::WA_NativeWindow set, 'glW' will not be destroyed. And then deleteTLSysExtra() will be called to 'splitter', in this function 'splitter's QWidgetWindow object will be deleted(and recursively deleted its child objects), remember that 'glW's QWidgetWindow object is a child of QWidgetWindow object of 'splitter' so it will be deleted too, this will make 'glW's topextra structure hold a deleted pointer of QWidgetWindow, that is the source of the crash later.

      Attachments

        1. qtbug35600_diag.patch
          3 kB
        2. qtbug35600.txt
          9 kB
        3. qtbug35600.zip
          4 kB
        4. testQt5Crash.rar
          5 kB
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            peppe Giuseppe D'Angelo
            jianliang79 liang jian
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes