Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 5

Qt-interest Archive, May 2008
Openning QMessageBox from asyncroniously called slot leads to crash


Message 1 in thread

I have an QHttp embedded into my wrapper that has :

ÂÂÂÂÂÂÂÂconnect(
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ_http , SIGNAL( requestFinished(int , bool) ),
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂthis , SLOT( requestProcessingFinished(int , bool) )
ÂÂÂÂÂÂÂÂ);

and has a slot:

void 
GetFile::requestProcessingFinished(int id_ , bool error_ )
{
...
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂemit sig_done(_fileName);
...
}

In main window I do:
ÂÂÂÂÂÂÂÂconnect(
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ&_getUpdateFile , SIGNAL( sig_done( QString ) ),
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂthis , SLOT( upgradeDownloaded(QString) ) /* , 
Qt::QueuedConnection */
ÂÂÂÂÂÂÂÂ);

where _getUpdateFile is an instance of my wrapper.
Inside ÂupgradeDownloaded I call some function that put's QMessage Box on the 
desktop like this:
ÂÂÂÂÂÂÂÂQMessageBox msgBox(0L);
ÂÂÂÂÂÂÂÂmsgBox.addButton(tr("Run"), QMessageBox::ActionRole);
ÂÂÂÂÂÂÂÂQPushButton *snoozeButton = msgBox.addButton(tr("Snooze and Run 
later"), 
QMessageBox::ActionRole);
ÂÂÂÂÂÂÂÂmsgBox.setText(tr("Update has been downloaded. Run update file or 
snooze and 
run later?"));
ÂÂÂÂÂÂÂÂmsgBox.setIcon(QMessageBox::Icon::Question);
ÂÂÂÂÂÂÂÂmsgBox.exec();

or just with QMessageBox convinience function.
If I do connect without placing explicit Qt:QueuedConnection - I get 
segmentation fault. If I put QueuedConnection explicitelly - everything is 
working well.
Is that should be the case that I MUST state what kind of connection I want? 
Should not it be automatic and be the care of QT?

The backtrace (under windows is):
ÂÂÂÂÂÂÂÂQtCored4.dll!QEventLoop::exit(int returnCode=0) ÂLine 237 + 0x3ÂC++
ÂÂÂÂÂÂÂÂQtGuid4.dll!QDialog::setVisible(bool visible=false) ÂLine 692ÂÂÂC++
ÂÂÂÂÂÂÂÂQtGuid4.dll!QWidget::hide() ÂLine 434 + 0x14ÂÂÂÂC++
ÂÂÂÂÂÂÂÂQtGuid4.dll!QDialog::~QDialog() ÂLine 253ÂÂÂÂÂÂÂC++
ÂÂÂÂÂÂÂÂQtGuid4.dll!QMessageBox::~QMessageBox() ÂLine 677 + 0x8ÂC++
ÂÂÂÂÂÂÂÂmsvcr71d.dll!_CallSettingFrame(unsigned long funclet=1228936, unsigned 
long 
pRN=259, unsigned long dwInCode=0) Â+ 0x27ÂÂÂÂÂÂAsm
ÂÂÂÂÂÂÂÂmsvcr71d.dll!__FrameUnwindToState(EHRegistrationNode * pRN=0x0012c088, 
void 
* pDC=0x00128f00, const _s_FuncInfo * pFuncInfo=0x65812f34, int 
targetState=-1) Â+ 
0xbfÂÂÂÂC++
ÂÂÂÂÂÂÂÂmsvcr71d.dll!__InternalCxxFrameHandler(EHExceptionRecord * 
pExcept=0x00129408, EHRegistrationNode * pRN=0x0012c088, _CONTEXT * 
pContext=0x00128f0c, void * 
pDC=0x00128f00, const _s_FuncInfo * pFuncInfo=0x65812f34, int CatchDepth=0, 
EHRegistrationNode * pMarkerRN=0x00000000, unsigned char recursive=0) Â+ 0x4dÂÂÂ
C++
>ÂÂÂÂÂÂÂmsvcr71d.dll!__CxxFrameHandler(EHExceptionRecord * pExcept=0x00129408, 
EHRegistrationNode * pRN=0x0012c088, void * pContext=0x00128f0c, void * 
pDC=0x00128f00) Â+ 
0x2cÂÂÂÂC++
ÂÂÂÂÂÂÂÂntdll.dll!7c9037bf() ÂÂÂ
ÂÂÂÂÂÂÂÂntdll.dll!7c90378b() ÂÂÂ
ÂÂÂÂÂÂÂÂntdll.dll!7c937b48() ÂÂÂ
ÂÂÂÂÂÂÂÂkernel32.dll!7c81eb33() ÂÂÂÂÂÂÂ

Message 2 in thread

Hi,

> [...]
>         msvcr71d.dll!__InternalCxxFrameHandler(EHExceptionRecord * 
> pExcept=0x00129408, EHRegistrationNode * pRN=0x0012c088, _CONTEXT * 
> pContext=0x00128f0c, void * 
> pDC=0x00128f00, const _s_FuncInfo * pFuncInfo=0x65812f34, int CatchDepth=0, 
> EHRegistrationNode * pMarkerRN=0x00000000, unsigned char recursive=0)  + 0x4d   
> C++
> [...]

I don't have much experience with Visual C++ programming, but it looks like 
something is wrong with the stack: it probably was overwritten. If so, there'a 
a memory error somewhere, probably in your program. I suggest you run your 
program in a memory debugger such as Purify.

-- 
 [ signature omitted ] 

Message 3 in thread

On Saturday 24 May 2008 08:51:29 Dimitri wrote:
> Hi,
>
> > [...]
> >         msvcr71d.dll!__InternalCxxFrameHandler(EHExceptionRecord *
> > pExcept=0x00129408, EHRegistrationNode * pRN=0x0012c088, _CONTEXT *
> > pContext=0x00128f0c, void *
> > pDC=0x00128f00, const _s_FuncInfo * pFuncInfo=0x65812f34, int
> > CatchDepth=0, EHRegistrationNode * pMarkerRN=0x00000000, unsigned char
> > recursive=0)  + 0x4d C++
> > [...]
>
> I don't have much experience with Visual C++ programming, but it looks like
> something is wrong with the stack: it probably was overwritten. If so,
> there'a a memory error somewhere, probably in your program. I suggest you
> run your program in a memory debugger such as Purify.

I think it is the same bug as this one:
http://trolltech.com/developer/task-tracker/index_html?method=entry&id=211362

It behaves almost the same.
I traced the code - it thrown an exception deep in QT event processing code. 
Additional observation: My code do not spawn any threads. When I debug the 
application there are 3 (or so) threads. Few seconds (mostly 1-2) after I run 
QMessageBox one of the threads terminates and then I got this problem.
I hope it is the same bug as I mention. 
I tryid it with QT 4.3.2 and 4.4.0. In both version it happens . Changing 
connection type somewhere in this chain between QHttp and the final slot that 
calls QMessageBox fixes the problem.

--
 [ signature omitted ] 

Message 4 in thread

Hi,

> I think it is the same bug as this one:
> http://trolltech.com/developer/task-tracker/index_html?method=entry&id=211362

Ah, it looks like this is a Qt issue after all.

The default connection is a DirectConnection, which results in the signal 
directly calling the slot.

When you specify a QueuedConnection, an event is sent to the event loop and 
the slot is called later, when the event is processed.

Specifying a QueuedConnection is a good workaround.

> It behaves almost the same.
> I traced the code - it thrown an exception deep in QT event processing code. 

What sort of exception?

-- 
 [ signature omitted ] 

Message 5 in thread

On Wednesday 28 May 2008 16:15:41 Dimitri wrote:
> Hi,
>
> > I think it is the same bug as this one:
> > http://trolltech.com/developer/task-tracker/index_html?method=entry&id=21
> >1362
>
> Ah, it looks like this is a Qt issue after all.
>
> The default connection is a DirectConnection, which results in the signal
> directly calling the slot.
>
> When you specify a QueuedConnection, an event is sent to the event loop and
> the slot is called later, when the event is processed.
>
> Specifying a QueuedConnection is a good workaround.
>
> > It behaves almost the same.
> > I traced the code - it thrown an exception deep in QT event processing
> > code.
>
> What sort of exception?

I did put QueuedConnection and it does it's work - no more crashes and works 
as expected.
About exception - I am not THAT familiar with qt internals ... but it seems as 
a result of processing an event. In output I see that QT cannot handle 
exceptions thrown from handlers.
I am not sure but it seems that the recipient is QHttp. 
If you can direct me to how I can identify the type of exception I will try to 
do it.
It seems though that the pattern is like this:
I get a signal and blocks the caller while I am running QMessageBox event 
loop. At the same time it seems that QHttp posts deleteLater (or alike) and 
some other signals. While I am in my slot running event loop the deleteLater 
is processed and some thread dies and then the same secondary event loop then 
try to delivier signal to something that either deleted or is in the stage to 
be deleted but waits me to complete my slot.
But again  - I am not sure in this since I am not familiar with QT internals 
(more precisely - it was first look into QT internals).
I though first that I violate reentrance requirements but now I do not think 
that it is the case since there is no additional calls to QHttp or any of my 
objects (that anyway are stateless and reentrance should not create problem)

--
 [ signature omitted ]