diff options
author | Denis Shienkov <denis.shienkov@gmail.com> | 2014-08-14 21:50:05 +0400 |
---|---|---|
committer | Denis Shienkov <denis.shienkov@gmail.com> | 2014-08-28 21:17:50 +0200 |
commit | b4d5bd813f591dc618e0fff2d55d93eeccb1a26e (patch) | |
tree | 1b08f7bea9b804501ce4b2181b1d66361a0059c8 /src/serialport/qserialport_win.cpp | |
parent | 286d64c202f461cb8ff5a4cc4c2320af8195b8f0 (diff) |
Fix a race condition at writing on Windowsv5.3.2
1. The writeStarted flag shall be reset to false after bytesWritten() signal
is emitted, but not before it.
2. In case of start of writing from the startAsyncWriteTimer it is necessary
to call the startAsyncWrite() method but not the completeAsyncWrite() method.
It give guarantees to exclude of race condition to multiple call of the
WriteFile twice until the write operation is not completed.
For example, a race condition is watched in case of writing data from the
slots which are connected to the bytesWritten() signal from a device; or to
the timeout() signal from a timer with zero interval. To checking of these
scenarios are added additional autotests.
Tested on Windows 8 with the on-board and USB serial ports, using Qt5.
Task-number: QTBUG-40769
Change-Id: Iedabbf38847debeee795a10fd7a4c54c65d2a338
Reviewed-by: Patrick Noffke <patrick.noffke@gmail.com>
Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com>
Diffstat (limited to 'src/serialport/qserialport_win.cpp')
-rw-r--r-- | src/serialport/qserialport_win.cpp | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index ecbf464a..18cef1ea 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -259,7 +259,7 @@ bool QSerialPortPrivate::setRequestToSend(bool set) bool QSerialPortPrivate::flush() { - return startAsyncWrite(); + return _q_startAsyncWrite(); } bool QSerialPortPrivate::clear(QSerialPort::Directions directions) @@ -313,7 +313,7 @@ void QSerialPortPrivate::startWriting() if (!writeStarted) { if (!startAsyncWriteTimer) { startAsyncWriteTimer = new QTimer(q); - q->connect(startAsyncWriteTimer, SIGNAL(timeout()), q, SLOT(_q_completeAsyncWrite())); + q->connect(startAsyncWriteTimer, SIGNAL(timeout()), q, SLOT(_q_startAsyncWrite())); startAsyncWriteTimer->setSingleShot(true); } startAsyncWriteTimer->start(0); @@ -327,7 +327,7 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs) QElapsedTimer stopWatch; stopWatch.start(); - if (!writeStarted && !startAsyncWrite()) + if (!writeStarted && !_q_startAsyncWrite()) return false; const qint64 initialReadBufferSize = readBuffer.size(); @@ -381,7 +381,7 @@ bool QSerialPortPrivate::waitForBytesWritten(int msecs) QElapsedTimer stopWatch; stopWatch.start(); - if (!writeStarted && !startAsyncWrite()) + if (!writeStarted && !_q_startAsyncWrite()) return false; forever { @@ -543,17 +543,18 @@ bool QSerialPortPrivate::_q_completeAsyncWrite() Q_Q(QSerialPort); if (writeStarted) { - writeStarted = false; const qint64 bytesTransferred = handleOverlappedResult(QSerialPort::Output, writeCompletionOverlapped); - if (bytesTransferred == qint64(-1)) + if (bytesTransferred == qint64(-1)) { + writeStarted = false; return false; - if (bytesTransferred > 0) { + } else if (bytesTransferred > 0) { writeBuffer.free(bytesTransferred); emit q->bytesWritten(bytesTransferred); } + writeStarted = false; } - return startAsyncWrite(); + return _q_startAsyncWrite(); } bool QSerialPortPrivate::startAsyncCommunication() @@ -605,7 +606,7 @@ bool QSerialPortPrivate::startAsyncRead() return true; } -bool QSerialPortPrivate::startAsyncWrite() +bool QSerialPortPrivate::_q_startAsyncWrite() { Q_Q(QSerialPort); |