Opened 17 years ago

Last modified 17 years ago

#34 assigned defect

Spontaneous traps of Qt applications during window management

Reported by: dmik Owned by: dmik
Priority: normal Milestone: qt-os2-3.3.1-rc07
Component: kernel Version: 3.3.1-rc06
Severity: normal Keywords:
Cc:

Description

Sometimes, a Qt application just traps in the middle of some window management (assumption). On my system, it happened a couple of times with Psi/2 upon attempts to show tooltips.

Change History (4)

comment:1 Changed 17 years ago by dmik

Status: newassigned

Thanks to our new exception handling, both times I've got the following call stack:

Frame[0].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QObject::parent() const] [8f6c+6]
 
Frame[1].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QWidget::parentWidget(bool) const] [8404+51]
 
Frame[2].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QWidget::topLevelWidget() const] [eee62+19]
 
Frame[3].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QtFrameProc] [3108+4a3]
 
Frame[4].Location.Module.name=[E:\Users\dmik\SysTraps\4\PMMERGE.DLL]
[SendMsg] [101ba4+266]
 
Frame[5].Location.Module.name=[E:\Users\dmik\SysTraps\4\PMMERGE.DLL]
[_WinSetMultWindowPos] [115234+4d]
 
Frame[6].Location.Module.name=[E:\Users\dmik\SysTraps\4\PMMERGE.DLL]
[WIN32SETWINDOWPOS] [113460+d6]
 
Frame[7].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QtSysMenuProc] [3b7a0+ac7]
 
Frame[8].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QWidget::raise()] [3f796+83]
 
Frame[9].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QWidget::show()] [f1254+3c4]
 
Frame[10].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QTipManager::showTip()] [214604+91b]
 
Frame[11].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QTipManager::add(QRect const&, QWidget*, QRect const&, QString const&, QToolTipGroup*, QString const&, QToolTip*, bool)] [213a7c+1d9]
 
Frame[12].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QTipManager::add(QWidget*, QRect const&, QString const&, QToolTipGroup*, QString const&, QToolTip*, bool)] [213cec+49]
 
Frame[13].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QToolTip::tip(QRect const&, QString const&)] [2156c0+36]
 
Frame[14].Location.Module.name=[D:\DEVELOP\QT\PORTS\PSI\PSIOS2\PSI.EXE]
[ContactView::maybeTip(QPoint const&)] [128d50+c5]
 
Frame[15].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QTipManager::showTip()] [214604+11a]
 
Frame[16].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QTipManager::qt_invoke(int, QUObject*)] [215e4a+89]
 
Frame[17].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QObject::activate_signal(QConnectionList*, QUObject*)] [b5f18+11a]
 
Frame[18].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QObject::activate_signal(int)] [b5d72+171]
 
Frame[19].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QTimer::timeout()] [499196+29]
 
Frame[20].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QTimer::event(QEvent*)] [de0aa+48]
 
Frame[21].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QApplication::internalNotify(QObject*, QEvent*)] [50868+397]
 
Frame[22].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QApplication::notify(QObject*, QEvent*)] [4fc88+1a7]
 
Frame[23].Location.Module.name=[D:\DEVELOP\QT\PORTS\PSI\PSIOS2\PSI.EXE]
[PsiApplication::notify(QObject*, QEvent*)] [1c1db8+17]
 
Frame[24].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QApplication::sendEvent(QObject*, QEvent*)] [8504+40]
 
Frame[25].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[qPMProcessConfigRequests()] [120a6+206]
 
Frame[26].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[qPMProcessConfigRequests()] [120a6+189]
 
Frame[27].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QPMAuxEventQueueWin::message(unsigned long, void*, void*)] [11f1e+e9]
 
Frame[28].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QPMObjectWindow::windowProc(unsigned long, unsigned long, void*, void*)] [11e6e+a5]
 
Frame[29].Location.Module.name=[E:\Users\dmik\SysTraps\4\PMMERGE.DLL]
[WIN32DISPATCHMSG] [1056b8+f5]
 
Frame[30].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QEventLoop::processEvents(unsigned)] [13da4+2b1]
 
Frame[31].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QEventLoop::enterLoop()] [6820a+59]
 
Frame[32].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QEventLoop::exec()] [68166+29]
 
Frame[33].Location.Module.name=[D:\DEVELOP\QT\QTPSI\BIN\DEBUG\QPSI.DLL]
[QApplication::exec()] [50cf0+1e]
 
Frame[34].Location.Module.name=[D:\DEVELOP\QT\PORTS\PSI\PSIOS2\PSI.EXE]
[main] [f2662+32a]

Frame[35].Location.Module.name=[D:\DEVELOP\QT\PORTS\PSI\PSIOS2\PSI.EXE]
[__text] [0+21]

comment:2 Changed 17 years ago by dmik

According to the disassembly, QObject::parent() does mov eax, [eax + 0x0C], but eax (this pointer) is 0xFFFFFFFF there, resulting into a typical access violation. Tracking the stack down, I see that this pointer is a result of calling parentWidget() on a QWidget pointer taken from the QWL_QTMODAL window word in QtFrameWindow?().

Two reasons can cause this:

  1. Window data is not initialized to 0 when the widget is created, so we get garbage when reading it before it was set/reset by a modal widget.
  2. qt_dispatchBlocked(), when leaving the modal state for a given modal widget, skips some widgets that it previously set as being blocked by the given modal widget (by storing the address of the modal widget in QWL_QTMODAL). As a result, the modal widget is deleted but other widgets still refer to it through their QWL_QTMODAL word.

Reason 1 is unlikely (I have never seen anything but 0 there after window creation; I'm quite sure PM does memset(ptr,0,len). However, I haven't found any information confirming that in PMREF, so it's more correct to set all window data to zero ourselves.

Reason 2 is hardly reproduceable, however, there is a !isHidden() check done when widgets are marked as being blocked/unblocked. It means that if the widget was hid after it has been blocked, but not shown again before the modal that made it bloced went away, it would never be unblocked. Well, it's quite possible in reality I think.

comment:3 Changed 17 years ago by dmik

Also, it's theoretically possible that other widget flags (involved in to the decision whether to block or not) are changed. It's however and should never happen (only reparentSys() is allowed to change flags of the existing widget), but QWidget::setWFlags is a public method, so...

comment:4 Changed 17 years ago by dmik

Both reasons should have been fixed now by changeset:153. I'll see if it was correct by testing it with Psi.

Note: See TracTickets for help on using tickets.