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 | |
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')
-rw-r--r-- | src/serialport/qserialport.h | 1 | ||||
-rw-r--r-- | src/serialport/qserialport_win.cpp | 19 | ||||
-rw-r--r-- | src/serialport/qserialport_win_p.h | 2 |
3 files changed, 12 insertions, 10 deletions
diff --git a/src/serialport/qserialport.h b/src/serialport/qserialport.h index d0f65b5e..8a0bbb11 100644 --- a/src/serialport/qserialport.h +++ b/src/serialport/qserialport.h @@ -287,6 +287,7 @@ private: Q_PRIVATE_SLOT(d_func(), bool _q_completeAsyncCommunication()) Q_PRIVATE_SLOT(d_func(), bool _q_completeAsyncRead()) Q_PRIVATE_SLOT(d_func(), bool _q_completeAsyncWrite()) + Q_PRIVATE_SLOT(d_func(), bool _q_startAsyncWrite()) #endif }; 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); diff --git a/src/serialport/qserialport_win_p.h b/src/serialport/qserialport_win_p.h index f4297ef5..cf30c189 100644 --- a/src/serialport/qserialport_win_p.h +++ b/src/serialport/qserialport_win_p.h @@ -108,7 +108,7 @@ public: bool startAsyncCommunication(); bool startAsyncRead(); - bool startAsyncWrite(); + bool _q_startAsyncWrite(); bool emulateErrorPolicy(); void emitReadyRead(); |