diff options
Diffstat (limited to 'src/shared/trk/trkdevice.cpp')
-rw-r--r-- | src/shared/trk/trkdevice.cpp | 60 |
1 files changed, 50 insertions, 10 deletions
diff --git a/src/shared/trk/trkdevice.cpp b/src/shared/trk/trkdevice.cpp index a303ba1c2d..a76cff79c2 100644 --- a/src/shared/trk/trkdevice.cpp +++ b/src/shared/trk/trkdevice.cpp @@ -436,15 +436,52 @@ void WriterThread::terminate() } #ifdef Q_OS_WIN -static inline bool overlappedSyncWrite(HANDLE file, const char *data, + +static inline QString msgTerminated(int size) +{ + return QString::fromLatin1("Terminated with %1 bytes pending.").arg(size); +} + +// Interruptible synchronous write function. +static inline bool overlappedSyncWrite(HANDLE file, + const bool &terminateFlag, + const char *data, DWORD size, DWORD *charsWritten, - OVERLAPPED *overlapped) + OVERLAPPED *overlapped, + QString *errorMessage) { if (WriteFile(file, data, size, charsWritten, overlapped)) return true; - if (GetLastError() != ERROR_IO_PENDING) + const DWORD writeError = GetLastError(); + if (writeError != ERROR_IO_PENDING) { + *errorMessage = QString::fromLatin1("WriteFile failed: %1").arg(winErrorMessage(writeError)); + return false; + } + // Wait for written or thread terminated + const DWORD timeoutMS = 200; + const unsigned maxAttempts = 20; + DWORD wr = WaitForSingleObject(overlapped->hEvent, timeoutMS); + for (unsigned n = 0; wr == WAIT_TIMEOUT && n < maxAttempts && !terminateFlag; + wr = WaitForSingleObject(overlapped->hEvent, timeoutMS), n++); + if (terminateFlag) { + *errorMessage = msgTerminated(size); + return false; + } + switch (wr) { + case WAIT_OBJECT_0: + break; + case WAIT_TIMEOUT: + *errorMessage = QString::fromLatin1("Write timed out."); + return false; + default: + *errorMessage = QString::fromLatin1("Error while waiting for WriteFile results: %1").arg(winErrorMessage(GetLastError())); + return false; + } + if (!GetOverlappedResult(file, overlapped, charsWritten, TRUE)) { + *errorMessage = QString::fromLatin1("Error writing %1 bytes: %2").arg(size).arg(winErrorMessage(GetLastError())); return false; - return GetOverlappedResult(file, overlapped, charsWritten, TRUE); + } + return true; } #endif @@ -453,8 +490,7 @@ bool WriterThread::write(const QByteArray &data, QString *errorMessage) QMutexLocker locker(&m_context->mutex); #ifdef Q_OS_WIN DWORD charsWritten; - if (!overlappedSyncWrite(m_context->device, data.data(), data.size(), &charsWritten, &m_context->writeOverlapped)) { - *errorMessage = QString::fromLatin1("Error writing data: %1").arg(winErrorMessage(GetLastError())); + if (!overlappedSyncWrite(m_context->device, m_terminate, data.data(), data.size(), &charsWritten, &m_context->writeOverlapped, errorMessage)) { return false; } FlushFileBuffers(m_context->device); @@ -473,8 +509,10 @@ bool WriterThread::trkWriteRawMessage(const TrkMessage &msg) const QByteArray ba = frameMessage(msg.code, msg.token, msg.data, m_context->serialFrame); QString errorMessage; const bool rc = write(ba, &errorMessage); - if (!rc) + if (!rc) { + qWarning("%s\n", qPrintable(errorMessage)); emit error(errorMessage); + } return rc; } @@ -844,7 +882,7 @@ TrkDevice::~TrkDevice() bool TrkDevice::open(const QString &port, QString *errorMessage) { if (d->verbose) - qDebug() << "Opening" << port << "is open: " << isOpen(); + qDebug() << "Opening" << port << "is open: " << isOpen() << " serialFrame=" << serialFrame(); close(); #ifdef Q_OS_WIN d->deviceContext->device = CreateFile(port.toStdWString().c_str(), @@ -917,8 +955,10 @@ void TrkDevice::close() { if (!isOpen()) return; - d->readerThread->terminate(); - d->writerThread->terminate(); + if (d->readerThread) + d->readerThread->terminate(); + if (d->writerThread) + d->writerThread->terminate(); #ifdef Q_OS_WIN CloseHandle(d->deviceContext->device); d->deviceContext->device = INVALID_HANDLE_VALUE; |