diff options
author | David Edmundson <davidedmundson@kde.org> | 2019-07-23 01:40:36 +0200 |
---|---|---|
committer | David Edmundson <davidedmundson@kde.org> | 2019-08-17 11:50:23 +0200 |
commit | 3e96fa1df8d2bc0ec8ab66abae1f20439b786b40 (patch) | |
tree | bff5e5d27f8499954724e517462fd955ff011a9c | |
parent | 2838c7f33a0b2f40b026d00b3e00139f94c358e7 (diff) | |
download | qtwayland-3e96fa1df8d2bc0ec8ab66abae1f20439b786b40.tar.gz |
Client: Fix large clipboard pasting
With the non-blocking file opening, when no data was available in the
pipe, read could return 0 even though we were not at the end of the
file. This resulted in truncated data when pasting the clipboard.
This patch uses select to block until a file is available, removing the
polling sleep. This means the file can be safely opened in blocking mode
whilst keeping the timeout feature allowing read to work as intended.
Change-Id: I936aa85e9f25197e7abe6fb3fa729b618c00924d
Reviewed-by: David Faure <david.faure@kdab.com>
Reviewed-by: Johan Helsing <johan.helsing@qt.io>
-rw-r--r-- | src/client/qwaylanddataoffer.cpp | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/src/client/qwaylanddataoffer.cpp b/src/client/qwaylanddataoffer.cpp index 0c732c02..3da16ed0 100644 --- a/src/client/qwaylanddataoffer.cpp +++ b/src/client/qwaylanddataoffer.cpp @@ -135,7 +135,7 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T } int pipefd[2]; - if (qt_safe_pipe(pipefd, O_NONBLOCK) == -1) { + if (qt_safe_pipe(pipefd) == -1) { qWarning("QWaylandMimeData: pipe2() failed"); return QVariant(); } @@ -158,23 +158,32 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T int QWaylandMimeData::readData(int fd, QByteArray &data) const { - char buf[4096]; - int retryCount = 0; - int n; - while (true) { - n = QT_READ(fd, buf, sizeof buf); - if (n == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && ++retryCount < 1000) - usleep(1000); - else - break; - } - if (retryCount >= 1000) + fd_set readset; + FD_ZERO(&readset); + FD_SET(fd, &readset); + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + int ready = select(FD_SETSIZE, &readset, nullptr, nullptr, &timeout); + if (ready < 0) { + qWarning() << "QWaylandDataOffer: select() failed"; + return -1; + } else if (ready == 0) { qWarning("QWaylandDataOffer: timeout reading from pipe"); - if (n > 0) { - data.append(buf, n); - n = readData(fd, data); + return -1; + } else { + char buf[4096]; + int n = QT_READ(fd, buf, sizeof buf); + + if (n > 0) { + data.append(buf, n); + n = readData(fd, data); + } else if (n < 0) { + qWarning("QWaylandDataOffer: read() failed"); + } + return n; } - return n; } } |