diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2023-06-08 17:53:29 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2023-06-09 20:30:07 -0700 |
commit | 01872d06d9a09c83f28b3ecebcb06f0ed81c5622 (patch) | |
tree | ee97271ff1269a1c0efdb8462a1b354d6ef3e6d6 /tests/auto/corelib/io/qfile | |
parent | 65097e7667c96177c322ebd45f7ac5c74fee7a26 (diff) |
tst_QFile: replicate the unixPipe test using FIFOs
Pipes are unnamed FIFOs, so they're basically the same.
The difference here is that open() blocks on opening a FIFO until both
ends of the FIFO are opened. This helps us in synchronizing the two
threads and thus ensuring that that the read() system call deep inside
QFile does, indeed, block.
We see this with strace -T on Linux:
[pid 662956] openat(AT_FDCWD, "/run/user/1000/tst_qfile_fifo.2575572361", O_RDONLY|O_CLOEXEC <unfinished ...>
... aux starts up ...
[pid 662957] prctl(PR_SET_NAME, "QThread") = 0 <0.000004>
[pid 662957] openat(AT_FDCWD, "/run/user/1000/tst_qfile_fifo.2575572361", O_WRONLY|O_CLOEXEC <unfinished ...>
[pid 662956] <... openat resumed>) = 4 <0.000133>
[pid 662957] <... openat resumed>) = 6 <0.000011>
[pid 662957] clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=0, tv_nsec=500000000}, <unfinished ...>
[pid 662956] read(4, <unfinished ...>
[pid 662957] <... clock_nanosleep resumed>NULL) = 0 <0.500183>
[pid 662957] write(6, "\2", 1) = 1 <0.000033>
[pid 662956] <... read resumed>"\2", 1) = 1 <0.500311>
Pick-to: 6.6
Change-Id: I63b988479db546dabffcfffd1766d7a48819b149
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'tests/auto/corelib/io/qfile')
-rw-r--r-- | tests/auto/corelib/io/qfile/tst_qfile.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index e2862e321c..64a3687e2a 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -13,6 +13,7 @@ #include <QDir> #include <QFile> #include <QFileInfo> +#include <QRandomGenerator> #include <QTemporaryDir> #include <QTemporaryFile> #include <QOperatingSystemVersion> @@ -227,6 +228,8 @@ private slots: #ifdef Q_OS_UNIX void unixPipe_data(); void unixPipe(); + void unixFifo_data() { unixPipe_data(); } + void unixFifo(); void socketPair_data() { unixPipe_data(); } void socketPair(); #endif @@ -2679,6 +2682,57 @@ void tst_QFile::unixPipe() qt_safe_close(pipes[1]); } +void tst_QFile::unixFifo() +{ + QByteArray fifopath = []() -> QByteArray { + QByteArray dir = qgetenv("XDG_RUNTIME_DIR"); + if (dir.isEmpty()) + dir = QFile::encodeName(QDir::tempPath()); + + // try to create a FIFO + for (int attempts = 10; attempts; --attempts) { + QByteArray fifopath = dir + "/tst_qfile_fifo." + + QByteArray::number(QRandomGenerator::global()->generate()); + int ret = mkfifo(fifopath, 0600); + if (ret == 0) + return fifopath; + } + + qWarning("Failed to create a FIFO at %s; last error was %s", + dir.constData(), strerror(errno)); + return {}; + }(); + if (fifopath.isEmpty()) + return; + + auto removeFifo = qScopeGuard([&fifopath] { unlink(fifopath); }); + + // with a FIFO, the two open() system calls synchronize + QScopedPointer<QThread> thr(QThread::create([&fifopath]() { + int fd = qt_safe_open(fifopath, O_WRONLY); + QTest::qSleep(500); + char c = 2; + qt_safe_write(fd, &c, 1); + qt_safe_close(fd); + })); + thr->start(); + + QFETCH(bool, useStdio); + QFile f; + if (useStdio) { + FILE *fh = fopen(fifopath, "rb"); + QVERIFY(f.open(fh, QIODevice::ReadOnly | QIODevice::Unbuffered, QFileDevice::AutoCloseHandle)); + } else { + f.setFileName(QFile::decodeName(fifopath)); + QVERIFY(f.open(QIODevice::ReadOnly | QIODevice::Unbuffered)); + } + + char c = 0; + QCOMPARE(f.read(&c, 1), 1); // this ought to block + QCOMPARE(c, '\2'); + thr->wait(); +} + void tst_QFile::socketPair() { int pipes[2] = { -1, -1 }; |