From 2c8d75ff6031706942d91ba9071878884683be0a Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Tue, 7 Nov 2023 11:11:59 +0100 Subject: [PATCH] QSharedMemory: fix attach() -> create() for legacy SystemV mode The attach() -> create() sequence was not covered by unit-tests in qtbase, but this approach is used inside QSharedImageLoader. It turns out that 02c42b26e1ff94047657c4838128cb5b22d24d2b broke this usecase for legacy mode, and the create() triggered an assertion in QSharedMemorySystemV::updateNativeKeyFile(). Fix it by clearing the nativeKeyFile if ftok() call in QSharedMemorySystemV::handle() fails(). Add unit-tests for the attach() -> create() scenario. These tests revealed that this scenario fails also in non-legacy mode for SystemV, so add QEXPECT_FAIL for these cases for now. This will be addressed in a separate patch. Change-Id: If133fa56c82eba902374dc48d2757046b3d40baf Reviewed-by: Fabian Kosmale Reviewed-by: Qt CI Bot (cherry picked from commit fb1dcbfcba35fe436b7be1c851a129da9f98cb55) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/ipc/qsharedmemory_systemv.cpp | 1 + .../ipc/qsharedmemory/tst_qsharedmemory.cpp | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/corelib/ipc/qsharedmemory_systemv.cpp b/src/corelib/ipc/qsharedmemory_systemv.cpp index 716b7aedd11..ddf9a36cd67 100644 --- a/src/corelib/ipc/qsharedmemory_systemv.cpp +++ b/src/corelib/ipc/qsharedmemory_systemv.cpp @@ -76,6 +76,7 @@ key_t QSharedMemorySystemV::handle(QSharedMemoryPrivate *self) unix_key = ftok(nativeKeyFile, int(self->nativeKey.type())); if (unix_key < 0) { self->setUnixErrorString("QSharedMemory::handle"_L1); + nativeKeyFile.clear(); unix_key = 0; } return unix_key; diff --git a/tests/auto/corelib/ipc/qsharedmemory/tst_qsharedmemory.cpp b/tests/auto/corelib/ipc/qsharedmemory/tst_qsharedmemory.cpp index cdbc4e5d8b3..8e7d0064ce7 100644 --- a/tests/auto/corelib/ipc/qsharedmemory/tst_qsharedmemory.cpp +++ b/tests/auto/corelib/ipc/qsharedmemory/tst_qsharedmemory.cpp @@ -56,6 +56,8 @@ private slots: void removeWhileAttached(); void emptyMemory(); void readOnly(); + void attachBeforeCreate_data(); + void attachBeforeCreate(); // basics all together void simpleProducerConsumer_data(); @@ -546,6 +548,39 @@ void tst_QSharedMemory::readOnly() #endif } +void tst_QSharedMemory::attachBeforeCreate_data() +{ + QTest::addColumn("legacy"); + + QTest::addRow("legacy") << true; + QTest::addRow("non-legacy") << false; +} + +void tst_QSharedMemory::attachBeforeCreate() +{ + QFETCH_GLOBAL(const QNativeIpcKey::Type, keyType); + QFETCH(const bool, legacy); + const QString keyStr(u"test"_s); + QNativeIpcKey key; + if (legacy) { + key = QSharedMemory::legacyNativeKey(keyStr, keyType); + // same as rememberKey(), but with legacy + if (!keys.contains(key)) { + keys.append(key); + remove(key); + } + } else { + key = rememberKey(keyStr); + } + const qsizetype sz = 100; + QSharedMemory mem(key); + QVERIFY(!mem.attach()); + // Fails for all SystemV backends now + if (!legacy && (keyType < QNativeIpcKey::Type::PosixRealtime)) + QEXPECT_FAIL("", "Not fixed yet", Continue); + QVERIFY(mem.create(sz)); +} + /*! Keep making shared memory until the kernel stops us. */