Discussion:
[Interest] Crash in QSerialPort when closing?
Murphy, Sean
2014-10-29 18:35:49 UTC
Permalink
I'm getting a weird issue where I can repeatedly cause a crash to happen in QSerialPort if I attempt to close the serial port when I'm in a slot connected to the readyRead() signal, and I'm just wondering if I'm doing something weird.

I've got a class that inherits from QSerialPort. I instantiate this object in the UI thread but immediately move it to a separate thread. This object has a slot, disconnectFromDevice(), that sends a reset command to the serial device.

So the way I intended the software to work is the user clicks the disconnect button in the UI thread, which sends a signal to the serial port object. That object sends the reset command to the serial device and the serial device responds with an acknowledge response. The acknowledge response triggers the QSerialPort::readyRead() signal, which triggers my readyRead() slot. I parse the acknowledge, then emit a signal back to the UI thread letting the UI know that the disconnect was successful, and then call QSerialPort::close() in the serial port object (still inside of my readyRead() slot).

When I execute setup in a debug build, at this point the application crashes with a SIGSEV. For some reason it kicks me into the disassembler instead of breaking in my code. If I comment out the close() call, the segfault doesn't happen.

Below is what's shown in the call stack, but since none of my code is shown in the call stack, I don't know if I'm crashing on the close() call itself, or if I crash sometime later because I'm doing something when the port isn't open. If I set a breakpoint anywhere in my readyRead() slot the crash DOESN'T occur. I only know that removing the close() call removes the crash.

Any ideas? Specifically, why am I not seeing any of my calls in the call stack?
Sean

0 ReadOverlappedCompletionNotifier::processCompletionRoutine qserialport_win.cpp 188 0x6704e8ed
1 AbstractOverlappedEventNotifier::event qserialport_win.cpp 119 0x6704e6d2
2 QApplicationPrivate::notify_helper qapplication.cpp 3467 0xa9ede0f
3 QApplication::notify qapplication.cpp 2888 0xa9eb72b
4 QCoreApplication::notifyInternal qcoreapplication.cpp 878 0x6b91b572
5 QCoreApplication::sendEvent qcoreapplication.h 232 0x6b9bee2b
6 QEventDispatcherWin32Private::activateEventNotifier qeventdispatcher_win.cpp 335 0x6b9646e8
7 QEventDispatcherWin32::processEvents qeventdispatcher_win.cpp 759 0x6b965de7
8 QEventLoop::processEvents qeventloop.cpp 136 0x6b919650
9 QEventLoop::exec qeventloop.cpp 212 0x6b9198eb
10 QThread::exec qthread.cpp 509 0x6b794f85
11 QThread::run qthread.cpp 576 0x6b7950ed
12 QThreadPrivate::start qthread_win.cpp 347 0x6b797ac2
13 msvcrt!_itow_s C:\windows\syswow64\msvcrt.dll 0x775d1287
14 msvcrt!_endthreadex C:\windows\syswow64\msvcrt.dll 0x775d1328
15 KERNEL32!BaseCleanupAppcompatCacheSupport C:\windows\syswow64\kernel32.dll 0x7594338a
16 ?? 0x16d0ffd4
17 ntdll!RtlpNtSetValueKey C:\windows\system32\ntdll.dll 0x77c19f72
18 ?? 0x166b7660
19 ntdll!RtlpNtSetValueKey C:\windows\system32\ntdll.dll 0x77c19f45
20 msvcrt!_endthreadex C:\windows\syswow64\msvcrt.dll 0x775d12e5
21 ??
Denis Shienkov
2014-10-29 18:47:28 UTC
Permalink
Hi.

Your version of QtSerialPort is too very old (according to call-stack).
Please update to latest (e.g. to 5.3.2/5.3.3).

BR,
Denis
I’m getting a weird issue where I can repeatedly cause a crash to
happen in QSerialPort if I attempt to close the serial port when I’m
in a slot connected to the readyRead() signal, and I’m just wondering
if I’m doing something weird.
I’ve got a class that inherits from QSerialPort. I instantiate this
object in the UI thread but immediately move it to a separate thread.
This object has a slot, disconnectFromDevice(), that sends a reset
command to the serial device.
So the way I intended the software to work is the user clicks the
disconnect button in the UI thread, which sends a signal to the serial
port object. That object sends the reset command to the serial device
and the serial device responds with an acknowledge response. The
acknowledge response triggers the QSerialPort::readyRead() signal,
which triggers my readyRead() slot. I parse the acknowledge, then
emit a signal back to the UI thread letting the UI know that the
disconnect was successful, and then call QSerialPort::close() in the
serial port object (still inside of my readyRead() slot).
When I execute setup in a debug build, at this point the application
crashes with a SIGSEV. For some reason it kicks me into the
disassembler instead of breaking in my code. If I comment out the
close() call, the segfault doesn’t happen.
Below is what’s shown in the call stack, but since none of my code is
shown in the call stack, I don’t know if I’m crashing on the close()
call itself, or if I crash sometime later because I’m doing something
when the port isn’t open. If I set a breakpoint anywhere in my
readyRead() slot the crash DOESN’T occur. I only know that removing
the close() call removes the crash.
Any ideas? Specifically, why am I not seeing any of my calls in the call stack?
Sean
0 ReadOverlappedCompletionNotifier::processCompletionRoutine
qserialport_win.cpp 188 0x6704e8ed
1 AbstractOverlappedEventNotifier::event qserialport_win.cpp
119 0x6704e6d2
2 QApplicationPrivate::notify_helper qapplication.cpp
3467 0xa9ede0f
3 QApplication::notify qapplication.cpp
2888 0xa9eb72b
4 QCoreApplication::notifyInternal qcoreapplication.cpp
878 0x6b91b572
5 QCoreApplication::sendEvent qcoreapplication.h 232
0x6b9bee2b
6 QEventDispatcherWin32Private::activateEventNotifier
qeventdispatcher_win.cpp 335 0x6b9646e8
7 QEventDispatcherWin32::processEvents
qeventdispatcher_win.cpp 759 0x6b965de7
8 QEventLoop::processEvents qeventloop.cpp 136 0x6b919650
9 QEventLoop::exec qeventloop.cpp
212 0x6b9198eb
10 QThread::exec qthread.cpp 509 0x6b794f85
11 QThread::run qthread.cpp 576 0x6b7950ed
12 QThreadPrivate::start qthread_win.cpp
347 0x6b797ac2
13 msvcrt!_itow_s C:\windows\syswow64\msvcrt.dll 0x775d1287
14 msvcrt!_endthreadex C:\windows\syswow64\msvcrt.dll
0x775d1328
15 KERNEL32!BaseCleanupAppcompatCacheSupport
C:\windows\syswow64\kernel32.dll 0x7594338a
16 ?? 0x16d0ffd4
17 ntdll!RtlpNtSetValueKey C:\windows\system32\ntdll.dll 0x77c19f72
18 ?? 0x166b7660
19 ntdll!RtlpNtSetValueKey C:\windows\system32\ntdll.dll 0x77c19f45
20 msvcrt!_endthreadex C:\windows\syswow64\msvcrt.dll
0x775d12e5
21 ??
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Murphy, Sean
2014-10-29 19:14:18 UTC
Permalink
Post by Denis Shienkov
Your version of QtSerialPort is too very old (according to call-stack).
Please update to latest (e.g. to 5.3.2/5.3.3).
I'll try to upgrade then. If that's all it is, that'd be great!
Sean
Post by Denis Shienkov
I’m getting a weird issue where I can repeatedly cause a crash to happen in QSerialPort if I attempt to close the
serial port when I’m in a slot connected to the readyRead() signal, and I’m just wondering if I’m doing something
weird.
 
I’ve got a class that inherits from QSerialPort.  I instantiate this object in the UI thread but immediately move it to a
separate thread.  This object has a slot, disconnectFromDevice(), that sends a reset command to the serial device.
 
So the way I intended the software to work is the user clicks the disconnect button in the UI thread, which sends a
signal to the serial port object.  That object sends the reset command to the serial device and the serial device
responds with an acknowledge response.  The acknowledge response triggers the QSerialPort::readyRead() signal,
which triggers my readyRead() slot.  I parse the acknowledge, then emit a signal back to the UI thread letting the
UI know that the disconnect was successful, and then call QSerialPort::close() in the serial port object (still inside of
my readyRead() slot). 
When I execute setup in a debug build, at this point the application crashes with a SIGSEV.  For some reason it kicks
me into the disassembler instead of breaking in my code.  If I comment out the close() call, the segfault doesn’t
happen.
Below is what’s shown in the call stack, but since none of my code is shown in the call stack, I don’t know if I’m
crashing on the close() call itself, or if I crash sometime later because I’m doing something when the port isn’t
open.  If I set a breakpoint anywhere in my readyRead() slot the crash DOESN’T occur.  I only know that removing
the close() call removes the crash.
Any ideas?  Specifically, why am I not seeing any of my calls in the call stack?
Sean
 
0              ReadOverlappedCompletionNotifier::processCompletionRoutine            qserialport_win.cpp       188         0x6704e8ed
1              AbstractOverlappedEventNotifier::event             qserialport_win.cpp       119        
2              QApplicationPrivate::notify_helper         qapplication.cpp               3467       0xa9ede0f
3              QApplication::notify       qapplication.cpp               2888       0xa9eb72b         
4              QCoreApplication::notifyInternal              qcoreapplication.cpp      878         0x6b91b572
5              QCoreApplication::sendEvent    qcoreapplication.h          232         0x6b9bee2b      
6              QEventDispatcherWin32Private::activateEventNotifier  qeventdispatcher_win.cpp         335         0x6b9646e8
7              QEventDispatcherWin32::processEvents               qeventdispatcher_win.cpp         759        
8              QEventLoop::processEvents       qeventloop.cpp                136        
9              QEventLoop::exec           qeventloop.cpp                212        
10           QThread::exec  qthread.cpp       509        
11           QThread::run     qthread.cpp       576        
12           QThreadPrivate::start    qthread_win.cpp             347        
13           msvcrt!_itow_s                C:\windows\syswow64\msvcrt.dll                          
14           msvcrt!_endthreadex   C:\windows\syswow64\msvcrt.dll                          
15           KERNEL32!BaseCleanupAppcompatCacheSupport            C:\windows\syswow64\kernel32.dll                       0x7594338a
16           ??                                          
17           ntdll!RtlpNtSetValueKey              C:\windows\system32\ntdll.dll                
18           ??                                          
19           ntdll!RtlpNtSetValueKey              C:\windows\system32\ntdll.dll                
20           msvcrt!_endthreadex   C:\windows\syswow64\msvcrt.dll                          
21           ??          
Murphy, Sean
2014-10-29 20:57:27 UTC
Permalink
Post by Murphy, Sean
Post by Denis Shienkov
Your version of QtSerialPort is too very old (according to call-stack).
Please update to latest (e.g. to 5.3.2/5.3.3).
I'll try to upgrade then. If that's all it is, that'd be great!
Looks like that has fixed the problem. Thanks for the help!
Sean
Tony Rietwyk
2014-10-30 00:03:22 UTC
Permalink
Hi Sean,



Closing a device within a read slot sounds dodgy anyway. In these cases, I
usually do QTimer::singleShot(0, ...) and do the close in that slot.



Regards,



Tony





From: interest-bounces+tony=***@qt-project.org
[mailto:interest-bounces+tony=***@qt-project.org] On Behalf Of
Murphy, Sean
Sent: Thursday, 30 October 2014 5:36 AM
To: ***@qt-project.org
Subject: [Interest] Crash in QSerialPort when closing?



I'm getting a weird issue where I can repeatedly cause a crash to happen in
QSerialPort if I attempt to close the serial port when I'm in a slot
connected to the readyRead() signal, and I'm just wondering if I'm doing
something weird.



I've got a class that inherits from QSerialPort. I instantiate this object
in the UI thread but immediately move it to a separate thread. This object
has a slot, disconnectFromDevice(), that sends a reset command to the serial
device.



So the way I intended the software to work is the user clicks the disconnect
button in the UI thread, which sends a signal to the serial port object.
That object sends the reset command to the serial device and the serial
device responds with an acknowledge response. The acknowledge response
triggers the QSerialPort::readyRead() signal, which triggers my readyRead()
slot. I parse the acknowledge, then emit a signal back to the UI thread
letting the UI know that the disconnect was successful, and then call
QSerialPort::close() in the serial port object (still inside of my
readyRead() slot).



When I execute setup in a debug build, at this point the application crashes
with a SIGSEV. For some reason it kicks me into the disassembler instead of
breaking in my code. If I comment out the close() call, the segfault
doesn't happen.



Below is what's shown in the call stack, but since none of my code is shown
in the call stack, I don't know if I'm crashing on the close() call itself,
or if I crash sometime later because I'm doing something when the port isn't
open. If I set a breakpoint anywhere in my readyRead() slot the crash
DOESN'T occur. I only know that removing the close() call removes the
crash.



Any ideas? Specifically, why am I not seeing any of my calls in the call
stack?

Sean



0 ReadOverlappedCompletionNotifier::processCompletionRoutine
qserialport_win.cpp 188 0x6704e8ed

1 AbstractOverlappedEventNotifier::event
qserialport_win.cpp 119 0x6704e6d2

2 QApplicationPrivate::notify_helper qapplication.cpp
3467 0xa9ede0f

3 QApplication::notify qapplication.cpp
2888 0xa9eb72b

4 QCoreApplication::notifyInternal
qcoreapplication.cpp 878 0x6b91b572

5 QCoreApplication::sendEvent qcoreapplication.h
232 0x6b9bee2b

6 QEventDispatcherWin32Private::activateEventNotifier
qeventdispatcher_win.cpp 335 0x6b9646e8

7 QEventDispatcherWin32::processEvents
qeventdispatcher_win.cpp 759 0x6b965de7

8 QEventLoop::processEvents qeventloop.cpp
136 0x6b919650

9 QEventLoop::exec qeventloop.cpp 212
0x6b9198eb

10 QThread::exec qthread.cpp 509 0x6b794f85


11 QThread::run qthread.cpp 576 0x6b7950ed


12 QThreadPrivate::start qthread_win.cpp 347
0x6b797ac2

13 msvcrt!_itow_s C:\windows\syswow64\msvcrt.dll
0x775d1287

14 msvcrt!_endthreadex C:\windows\syswow64\msvcrt.dll
0x775d1328

15 KERNEL32!BaseCleanupAppcompatCacheSupport
C:\windows\syswow64\kernel32.dll 0x7594338a


16 ?? 0x16d0ffd4


17 ntdll!RtlpNtSetValueKey
C:\windows\system32\ntdll.dll 0x77c19f72

18 ?? 0x166b7660

19 ntdll!RtlpNtSetValueKey
C:\windows\system32\ntdll.dll 0x77c19f45

20 msvcrt!_endthreadex C:\windows\syswow64\msvcrt.dll
0x775d12e5

21 ??
Reinhardt Behm
2014-10-30 00:44:16 UTC
Permalink
This is the more complicated way.

Just use deleterLater(). It has the same effect. After the next round the
eventloop the object will be deleted.
--
Best Regards

Reinhardt Behm

mailto: ***@hushmail.com
Skype: reinhardt.behm
Post by Tony Rietwyk
Hi Sean,
Closing a device within a read slot sounds dodgy anyway. In these cases, I
usually do QTimer::singleShot(0, ...) and do the close in that slot.
Regards,
Tony
Murphy, Sean
2014-10-30 13:33:43 UTC
Permalink
Post by Reinhardt Behm
This is the more complicated way.
Just use deleterLater(). It has the same effect. After the next round the
eventloop the object will be deleted.
I'm not trying to delete the serial port object, I'm just trying to close the serial port so that I stop listening.
Sean
Reinhardt Behm
2014-10-31 01:03:23 UTC
Permalink
Sorry, I mis-understood you and thought wanted to delete the object. This is
definitely a no-no inside the slot.
I saw you on windows which creates a thread for handling the device.
I have not looked into it, but it could be that it is trying to stop/delete
this thread when closing. This could lead to the crash.
But this is only handwaving :-)
--
Best Regards

Reinhardt Behm
Post by Murphy, Sean
Post by Reinhardt Behm
This is the more complicated way.
Just use deleterLater(). It has the same effect. After the next round the
eventloop the object will be deleted.
I'm not trying to delete the serial port object, I'm just trying to close
the serial port so that I stop listening. Sean
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Murphy, Sean
2014-10-30 13:42:39 UTC
Permalink
Closing a device within a read slot sounds dodgy anyway. In these cases, I usually do
QTimer::singleShot(0, ...) and do the close in that slot.
I thought about doing the single shot as well.

Is there a more concrete reason (other than it sounding "dodgy") that you feel like the way I'm currently doing it is not a good idea?

In my use case, I've already sent the "I would like to disconnect" command to the external device, and I'm waiting for a short acknowledge response. In my readyRead() slot, I validate that response, which means that the external device is in an idle state, listening, so I'm not expecting to receive any more bytes. So at this point, I'm ready to close the connection.

Sean
Tony Rietwyk
2014-10-31 01:46:08 UTC
Permalink
Sent: Friday, 31 October 2014 12:43 AM
Post by Tony Rietwyk
Closing a device within a read slot sounds dodgy anyway. In these
cases, I usually do QTimer::singleShot(0, ...) and do the close in that
slot.
I thought about doing the single shot as well.
Is there a more concrete reason (other than it sounding "dodgy") that you
feel like the way I'm currently doing it is not a good idea?
In my use case, I've already sent the "I would like to disconnect" command
to
the external device, and I'm waiting for a short acknowledge response. In
my readyRead() slot, I validate that response, which means that the
external
device is in an idle state, listening, so I'm not expecting to receive any
more
bytes. So at this point, I'm ready to close the connection.
Sean
I don't have anything more concrete than the example you've already pointed
out! Qt coders have to do special things to handle these cases around the
emit call - which was presumably not done correctly in the original version
of serial port. A device often has associated buffers, state flags and
other resources that are released or modified when you close the device.
Doing that in the middle of a read event assumes that the event has
completely finished with the resources and state flags.

I suppose a different way of thinking about it is to look at the code in a
procedural context: You would normally open the device, loop reading until
an end condition, then close the device. It would be weird for the read or
set-end-condition routines to close the device as well - since you may want
to reset the device and read again in a separate loop, without having to
reopening it.

Regards,

Tony

Loading...