Skip to content

Commit

Permalink
Add an option to flush writes.
Browse files Browse the repository at this point in the history
There is a bug with QLocalSockets on Windows where data will be silently
dropped if two consecutive writes are performed without flushing and the
remote end hasn't read all the data between the two (see
https://bugreports.qt.io/browse/QTBUG-18385). Since qmsgpack performs
several write operations as part of a single stream output, it must allow
callers to specify whether to flush writes in order to work around this
bug.
  • Loading branch information
mtstickney committed Feb 27, 2017
1 parent 067c727 commit ca56d9e
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
28 changes: 24 additions & 4 deletions src/msgpackstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,23 @@
return retVal;

MsgPackStream::MsgPackStream() :
dev(0), owndev(false), q_status(Ok)
dev(0), owndev(false), q_status(Ok), flushWrites(false)
{ }

MsgPackStream::MsgPackStream(QIODevice *d) :
dev(d), owndev(false), q_status(Ok)
dev(d), owndev(false), q_status(Ok), flushWrites(false)
{ }

MsgPackStream::MsgPackStream(QByteArray *a, QIODevice::OpenMode mode) :
owndev(true), q_status(Ok)
owndev(true), q_status(Ok), flushWrites(false)
{
QBuffer *buf = new QBuffer(a);
buf->open(mode);
dev = buf;
}

MsgPackStream::MsgPackStream(const QByteArray &a) :
owndev(true), q_status(Ok)
owndev(true), q_status(Ok), flushWrites(false)
{
QBuffer *buf = new QBuffer();
buf->setData(a);
Expand Down Expand Up @@ -87,6 +87,16 @@ void MsgPackStream::setStatus(Status status)
q_status = status;
}

void MsgPackStream::setFlushWrites(bool flush)
{
flushWrites = flush;
}

bool MsgPackStream::willFlushWrites()
{
return flushWrites;
}

MsgPackStream &MsgPackStream::operator>>(bool &b)
{
CHECK_STREAM_PRECOND(*this)
Expand Down Expand Up @@ -503,6 +513,16 @@ bool MsgPackStream::writeBytes(const char *data, uint len)
setStatus(WriteFailed);
return false;
}
/* Apparently on Windows, the buffer size for named pipes is 0, and
* any data that is written before the remote end reads it is
* dropped (!!) without error (see https://bugreports.qt.io/browse/QTBUG-18385).
* We must be very sure that the data has been written before we try
* another write. This degrades performance in other cases, so callers
* must enable this behavior explicitly.
*/
if (this->flushWrites) {
dev->waitForBytesWritten(-1);
}

/* Increment the write pointer and the total byte count. */
data += thisWrite;
Expand Down
3 changes: 3 additions & 0 deletions src/msgpackstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class MSGPACK_EXPORT MsgPackStream
Status status() const;
void resetStatus();
void setStatus(Status status);
void setFlushWrites(bool flushWrites);
bool willFlushWrites();

MsgPackStream &operator>>(bool &b);
MsgPackStream &operator>>(quint8 &u8);
Expand Down Expand Up @@ -60,6 +62,7 @@ class MSGPACK_EXPORT MsgPackStream
QIODevice *dev;
bool owndev;
Status q_status;
bool flushWrites;

bool unpack_longlong(qint64 &i64);
bool unpack_ulonglong(quint64 &u64);
Expand Down

0 comments on commit ca56d9e

Please sign in to comment.