[Interest] QNetwork problem in threaded application (repost from development).

Thiago Macieira thiago.macieira at intel.com
Tue Sep 10 18:03:05 CEST 2013


On terça-feira, 10 de setembro de 2013 17:29:19, Benjamin Zeller wrote:
> I did some more debugging today, something changed but its still
> crashing at the same place:
> 
> - The QAbstractSocket now has a QAdoptedThread affinity
> - The QAbstractSocket has a 0x0 pointer to the engine
> - The QAbstractSocketEngine has a WorkerThread affinity
> - The QAbstractSocketEngine has no parent (0x0)
> - The QReadNotifier has a WorkerThread affinity

The first question I'd ask if I hadn't been debugging this with you yesterday 
would be how you had got access to a socket engine if the socket engine is 
null.

I know the answer: you can see the socket engine in the stack of the crashing 
thread. If the pointer leading to it is null, we must conclude that the 
pointer was set to null after the call was placed. There are two 
possibilities:

1) it was done by another thread
2) it was done by this thread, via recursion back to the socket

I can tell you #2 doesn't happen. So it has to be #1.

Also, since the socket engine and the notifier have been deleted, any memory 
you read from them must be taken with a grain of salt.

> Isn't it weird that i still can read valid data from the this
> pointer when i'm in a QAbstractSocketEngine:: member func,
> event if its a 0 pointer in the QAbstractSocket?

It would be, if we didn't know what was happening. See above.

> i tried to put a thread test in
> void QAbstractSocketPrivate::resetSocketLayer()
> with no luck, seems the correct thread is the first one here.

What's "correct" here?

We concluded that both threads realise the socket closed and both threads go 
on to delete the engine.

> If you have any other idea where i can put in some testcode
> let me know and i will try. I have a extra qt compiled for
> development and can put in testcode easily.
> 
> Here you can see what i pointed out, different thread
> affinities and broken parentship (i assume QAbstractSocketEngine
> should have a parent):

It did. But since it has already been deleted, you're reading from a dangling 
pointer. You're looking at the engine after the destructor has run and the 
memory block possibly overwritten. If you turn off the pretty printers from 
gdb, you may be able to see the vptr in that object pointing elsewhere too.

> backtrace:
> 0	QCoreApplication::instance	qcoreapplication.h	115	0x7fbe903103d1
> 1	<function called from gdb>			0x7ffff41a925f
> 2	typeinfo name for QObjectPrivate	/opt/Qt/5.1.1/lib/libQt5Core.so.5
> 0x7fbe8ff1e050
> 3	QAbstractSocketPrivate::canReadNotification	qabstractsocket.cpp	745
> 0x7fbe90338f5d
[cut]

Please note that Qt Creator copy & paste backtraces are useless to me (unless 
need very little information). The most interesting information we can get 
from a backtrace are the parameters to the functions, which this backtrace 
does not show.

Creator includes that when you ask for a full backtrace. But then it includes 
a lot of other stuff that makes the backtrace hard to read.

The backtrace I want is what gdb prints with simply "bt". There's no Creator 
feature to get that. So when pasting backtraces to a mailing list, use gdb 
directly, not Qt Creator, or edit the locals out of the full backtrace.

> Btw, what would happen if the thread does not enter a eventloop but
> instead handle the socket in a blocking mode, then pushes it back to
> the mainthread? Would the move be correct?

I thought it was doing that. Your first backtrace showed it crashing in 
waitForBytesWritten.

> I think QSocketNotifier uses a posted event to reenable itself after
> a move... which means this is not delivered properly

That is a good point. But the notifier isn't needed if you're using the 
blocking waitForXXX functions, since those do select() directly on the socket, 
bypassing the notifier. In any case, a socket notifier only works if the control 
is returned to the event loop. If the control is returned to the event loop, 
then it reenables itself.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 190 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20130910/9ad66e90/attachment.sig>


More information about the Interest mailing list