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

Benjamin Zeller zeller.benjamin at web.de
Wed Sep 11 16:14:35 CEST 2013


Ok,

i implemented a simple testcase (as simple as possible).
And it crashes at exactly the same place.

The testcode is attached to the mail!

I ran 7 instances of autobench against it (httperf needs to be
installed), but maybe it will crash sooner or later if only one
is running:

http://www.xenoclast.org/autobench/

autobench --single_host --host1 192.168.2.101 --port1 8080 --uri1 
/index.html --quiet     \
          --low_rate 1500 --high_rate 2000 --rate_step 20 --num_call 10 \
          --num_conn 5000 --timeout 5 --file results.tsv



On 10.09.2013 18:03, Thiago Macieira wrote:
> 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.
>
>
>
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest
>

-------------- next part --------------
#-------------------------------------------------
#
# Project created by QtCreator 2013-09-11T11:50:43
#
#-------------------------------------------------

CONFIG += C++11

QT       += core network

QT       -= gui

TARGET = server
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE = app


SOURCES += main.cpp
-------------- next part --------------
A non-text attachment was scrubbed...
Name: main.cpp
Type: text/x-c++src
Size: 8519 bytes
Desc: not available
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20130911/a3a8bd05/attachment.cpp>


More information about the Interest mailing list