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 <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
(cherry picked from commit fb1dcbfcba35fe436b7be1c851a129da9f98cb55)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Ivan Solovev 2023-11-07 11:11:59 +01:00 committed by Qt Cherry-pick Bot
parent 96e9d5cd76
commit 2c8d75ff60
2 changed files with 36 additions and 0 deletions

View File

@ -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;

View File

@ -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<bool>("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.
*/