summaryrefslogtreecommitdiffstats
path: root/src/corelib/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/ipc')
-rw-r--r--src/corelib/ipc/qsharedmemory.cpp39
-rw-r--r--src/corelib/ipc/qsharedmemory.h5
-rw-r--r--src/corelib/ipc/qsharedmemory_p.h4
-rw-r--r--src/corelib/ipc/qsharedmemory_posix.cpp8
-rw-r--r--src/corelib/ipc/qsharedmemory_systemv.cpp5
-rw-r--r--src/corelib/ipc/qsystemsemaphore.cpp27
-rw-r--r--src/corelib/ipc/qsystemsemaphore.h5
-rw-r--r--src/corelib/ipc/qsystemsemaphore_p.h2
-rw-r--r--src/corelib/ipc/qsystemsemaphore_posix.cpp14
-rw-r--r--src/corelib/ipc/qsystemsemaphore_systemv.cpp8
-rw-r--r--src/corelib/ipc/qtipccommon.cpp246
-rw-r--r--src/corelib/ipc/qtipccommon.h107
-rw-r--r--src/corelib/ipc/qtipccommon_p.h37
13 files changed, 285 insertions, 222 deletions
diff --git a/src/corelib/ipc/qsharedmemory.cpp b/src/corelib/ipc/qsharedmemory.cpp
index 9e33b1d995..02761c0263 100644
--- a/src/corelib/ipc/qsharedmemory.cpp
+++ b/src/corelib/ipc/qsharedmemory.cpp
@@ -7,6 +7,7 @@
#include "qtipccommon_p.h"
#include "qsystemsemaphore.h"
+#include <q20memory.h>
#include <qdebug.h>
#ifdef Q_OS_WIN
# include <qt_windows.h>
@@ -23,15 +24,6 @@ QT_BEGIN_NAMESPACE
using namespace QtIpcCommon;
using namespace Qt::StringLiterals;
-#if __cplusplus >= 202002L
-using std::construct_at;
-#else
-template <typename T> static void construct_at(T *ptr)
-{
- new (ptr) T;
-}
-#endif
-
QSharedMemoryPrivate::~QSharedMemoryPrivate()
{
destructBackend();
@@ -39,6 +31,7 @@ QSharedMemoryPrivate::~QSharedMemoryPrivate()
inline void QSharedMemoryPrivate::constructBackend()
{
+ using namespace q20;
visit([](auto p) { construct_at(p); });
}
@@ -132,24 +125,17 @@ QSharedMemory::QSharedMemory(const QNativeIpcKey &key, QObject *parent)
setNativeKey(key);
}
-#if QT_DEPRECATED_SINCE(6, 10)
/*!
- \deprecated
-
Constructs a shared memory object with the given \a parent and with
the legacy key set to \a key. Because its key is set, its create() and
attach() functions can be called.
- Legacy keys are deprecated. See \l{Native IPC Keys} for more information.
-
\sa setKey(), create(), attach()
*/
QSharedMemory::QSharedMemory(const QString &key, QObject *parent)
: QSharedMemory(legacyNativeKey(key), parent)
{
- d_func()->legacyKey = key;
}
-#endif
/*!
The destructor clears the key, which forces the shared memory object
@@ -168,9 +154,7 @@ QSharedMemory::~QSharedMemory()
d->cleanHandle();
}
-#if QT_DEPRECATED_SINCE(6, 10)
/*!
- \deprecated
\overload
Sets the legacy \a key for this shared memory object. If \a key is the same
@@ -192,11 +176,8 @@ QSharedMemory::~QSharedMemory()
*/
void QSharedMemory::setKey(const QString &key)
{
- Q_D(QSharedMemory);
setNativeKey(legacyNativeKey(key));
- d->legacyKey = key;
}
-#endif
/*!
\since 4.8
@@ -252,7 +233,6 @@ void QSharedMemory::setNativeKey(const QNativeIpcKey &key)
if (isAttached())
detach();
d->cleanHandle();
- d->legacyKey = QString();
if (key.type() == d->nativeKey.type()) {
// we can reuse the backend
d->nativeKey = key;
@@ -269,7 +249,11 @@ bool QSharedMemoryPrivate::initKey(SemaphoreAccessMode mode)
if (!cleanHandle())
return false;
#if QT_CONFIG(systemsemaphore)
- systemSemaphore.setNativeKey(semaphoreNativeKey(), 1, mode);
+ const QString legacyKey = QNativeIpcKeyPrivate::legacyKey(nativeKey);
+ const QNativeIpcKey semKey = legacyKey.isEmpty()
+ ? semaphoreNativeKey()
+ : QSystemSemaphore::legacyNativeKey(legacyKey, nativeKey.type());
+ systemSemaphore.setNativeKey(semKey, 1, mode);
if (systemSemaphore.error() != QSystemSemaphore::NoError) {
QString function = "QSharedMemoryPrivate::initKey"_L1;
errorString = QSharedMemory::tr("%1: unable to set key on lock (%2)")
@@ -305,9 +289,7 @@ bool QSharedMemoryPrivate::initKey(SemaphoreAccessMode mode)
return true;
}
-#if QT_DEPRECATED_SINCE(6, 10)
/*!
- \deprecated
Returns the legacy key assigned with setKey() to this shared memory, or a null key
if no key has been assigned, or if the segment is using a nativeKey(). The
key is the identifier used by Qt applications to identify the shared memory
@@ -321,9 +303,8 @@ bool QSharedMemoryPrivate::initKey(SemaphoreAccessMode mode)
QString QSharedMemory::key() const
{
Q_D(const QSharedMemory);
- return d->legacyKey;
+ return QNativeIpcKeyPrivate::legacyKey(d->nativeKey);
}
-#endif
/*!
\since 4.8
@@ -693,12 +674,12 @@ bool QSharedMemory::isKeyTypeSupported(QNativeIpcKey::Type type)
QNativeIpcKey QSharedMemory::platformSafeKey(const QString &key, QNativeIpcKey::Type type)
{
- return { QtIpcCommon::platformSafeKey(key, IpcType::SharedMemory, type), type };
+ return QtIpcCommon::platformSafeKey(key, IpcType::SharedMemory, type);
}
QNativeIpcKey QSharedMemory::legacyNativeKey(const QString &key, QNativeIpcKey::Type type)
{
- return { legacyPlatformSafeKey(key, IpcType::SharedMemory, type), type };
+ return QtIpcCommon::legacyPlatformSafeKey(key, IpcType::SharedMemory, type);
}
#endif // QT_CONFIG(sharedmemory)
diff --git a/src/corelib/ipc/qsharedmemory.h b/src/corelib/ipc/qsharedmemory.h
index f8218cb0fe..ab448b15c1 100644
--- a/src/corelib/ipc/qsharedmemory.h
+++ b/src/corelib/ipc/qsharedmemory.h
@@ -50,14 +50,9 @@ public:
QSharedMemory(const QNativeIpcKey &key, QObject *parent = nullptr);
~QSharedMemory();
-#if QT_DEPRECATED_SINCE(6, 10)
- QT_DEPRECATED_VERSION_X_6_10("Please refer to 'Native IPC Key' documentation")
QSharedMemory(const QString &key, QObject *parent = nullptr);
- QT_DEPRECATED_VERSION_X_6_10("Please refer to 'Native IPC Key' documentation")
void setKey(const QString &key);
- QT_DEPRECATED_VERSION_X_6_10("Please refer to 'Native IPC Key' documentation")
QString key() const;
-#endif
void setNativeKey(const QNativeIpcKey &key);
void setNativeKey(const QString &key, QNativeIpcKey::Type type = QNativeIpcKey::legacyDefaultTypeForOs())
diff --git a/src/corelib/ipc/qsharedmemory_p.h b/src/corelib/ipc/qsharedmemory_p.h
index 3a6cd8c137..987bb38642 100644
--- a/src/corelib/ipc/qsharedmemory_p.h
+++ b/src/corelib/ipc/qsharedmemory_p.h
@@ -43,7 +43,7 @@ class QSharedMemoryLocker
{
public:
- inline QSharedMemoryLocker(QSharedMemory *sharedMemory) : q_sm(sharedMemory)
+ Q_NODISCARD_CTOR QSharedMemoryLocker(QSharedMemory *sharedMemory) : q_sm(sharedMemory)
{
Q_ASSERT(q_sm);
}
@@ -205,8 +205,6 @@ public:
}
QNativeIpcKey semaphoreNativeKey() const;
#endif // QT_CONFIG(systemsemaphore)
-
- QString legacyKey; // deprecated
};
QT_END_NAMESPACE
diff --git a/src/corelib/ipc/qsharedmemory_posix.cpp b/src/corelib/ipc/qsharedmemory_posix.cpp
index 744a6d67a4..582c6628e1 100644
--- a/src/corelib/ipc/qsharedmemory_posix.cpp
+++ b/src/corelib/ipc/qsharedmemory_posix.cpp
@@ -10,6 +10,7 @@
#include <errno.h>
+#if QT_CONFIG(sharedmemory)
#if QT_CONFIG(posix_shm)
#include <sys/types.h>
#include <sys/mman.h>
@@ -66,7 +67,7 @@ bool QSharedMemoryPosix::create(QSharedMemoryPrivate *self, qsizetype size)
const QByteArray shmName = QFile::encodeName(self->nativeKey.nativeKey());
int fd;
- EINTR_LOOP(fd, ::shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0600));
+ QT_EINTR_LOOP(fd, ::shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0600));
if (fd == -1) {
const int errorNumber = errno;
const auto function = "QSharedMemory::attach (shm_open)"_L1;
@@ -83,7 +84,7 @@ bool QSharedMemoryPosix::create(QSharedMemoryPrivate *self, qsizetype size)
// the size may only be set once
int ret;
- EINTR_LOOP(ret, QT_FTRUNCATE(fd, size));
+ QT_EINTR_LOOP(ret, QT_FTRUNCATE(fd, size));
if (ret == -1) {
self->setUnixErrorString("QSharedMemory::create (ftruncate)"_L1);
qt_safe_close(fd);
@@ -102,7 +103,7 @@ bool QSharedMemoryPosix::attach(QSharedMemoryPrivate *self, QSharedMemory::Acces
const int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR);
const mode_t omode = (mode == QSharedMemory::ReadOnly ? 0400 : 0600);
- EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag | O_CLOEXEC, omode));
+ QT_EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag | O_CLOEXEC, omode));
if (hand == -1) {
const int errorNumber = errno;
const auto function = "QSharedMemory::attach (shm_open)"_L1;
@@ -192,3 +193,4 @@ bool QSharedMemoryPosix::detach(QSharedMemoryPrivate *self)
QT_END_NAMESPACE
#endif // QT_CONFIG(posix_shm)
+#endif // QT_CONFIG(sharedmemory)
diff --git a/src/corelib/ipc/qsharedmemory_systemv.cpp b/src/corelib/ipc/qsharedmemory_systemv.cpp
index cc98b560ae..dc9de11091 100644
--- a/src/corelib/ipc/qsharedmemory_systemv.cpp
+++ b/src/corelib/ipc/qsharedmemory_systemv.cpp
@@ -11,6 +11,7 @@
#include <errno.h>
+#if QT_CONFIG(sharedmemory)
#if QT_CONFIG(sysv_shm)
#include <sys/types.h>
#include <sys/ipc.h>
@@ -75,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;
@@ -158,6 +160,8 @@ bool QSharedMemorySystemV::attach(QSharedMemoryPrivate *self, QSharedMemory::Acc
int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0400 : 0600));
if (-1 == id) {
self->setUnixErrorString("QSharedMemory::attach (shmget)"_L1);
+ unix_key = 0;
+ nativeKeyFile.clear();
return false;
}
@@ -205,3 +209,4 @@ bool QSharedMemorySystemV::detach(QSharedMemoryPrivate *self)
QT_END_NAMESPACE
#endif // QT_CONFIG(sysv_shm)
+#endif // QT_CONFIG(sharedmemory)
diff --git a/src/corelib/ipc/qsystemsemaphore.cpp b/src/corelib/ipc/qsystemsemaphore.cpp
index 0f59b378a3..4c24ef6043 100644
--- a/src/corelib/ipc/qsystemsemaphore.cpp
+++ b/src/corelib/ipc/qsystemsemaphore.cpp
@@ -68,25 +68,13 @@ inline void QSystemSemaphorePrivate::destructBackend()
\sa {Inter-Process Communication}, QSharedMemory, QSemaphore
*/
-#if QT_DEPRECATED_SINCE(6, 10)
/*!
- \deprecated
-
- Requests a system semaphore identified by the legacy key \a key. This
- constructor does the same as:
-
- \code
- QSystemSemaphore(QSystemSemaphore::legacyNativeKey(key), initialValue, mode)
- \endcode
-
- except that it stores the legacy native key to retrieve using key().
+ Requests a system semaphore identified by the legacy key \a key.
*/
QSystemSemaphore::QSystemSemaphore(const QString &key, int initialValue, AccessMode mode)
: QSystemSemaphore(legacyNativeKey(key), initialValue, mode)
{
- d->legacyKey = key;
}
-#endif
/*!
Requests a system semaphore for the specified \a key. The parameters
@@ -210,8 +198,6 @@ void QSystemSemaphore::setNativeKey(const QNativeIpcKey &key, int initialValue,
}
d->initialValue = initialValue;
d->handle(mode);
-
- d->legacyKey.clear();
}
/*!
@@ -229,9 +215,7 @@ QNativeIpcKey QSystemSemaphore::nativeIpcKey() const
return d->nativeKey;
}
-#if QT_DEPRECATED_SINCE(6, 10)
/*!
- \deprecated
This function works the same as the constructor. It reconstructs
this QSystemSemaphore object. If the new \a key is different from
the old key, calling this function is like calling the destructor of
@@ -244,11 +228,9 @@ QNativeIpcKey QSystemSemaphore::nativeIpcKey() const
void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode mode)
{
setNativeKey(legacyNativeKey(key), initialValue, mode);
- d->legacyKey = key;
}
/*!
- \deprecated
Returns the legacy key assigned to this system semaphore. The key is the
name by which the semaphore can be accessed from other processes.
@@ -256,9 +238,8 @@ void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode m
*/
QString QSystemSemaphore::key() const
{
- return d->legacyKey;
+ return QNativeIpcKeyPrivate::legacyKey(d->nativeKey);
}
-#endif
/*!
Acquires one of the resources guarded by this semaphore, if there is
@@ -406,12 +387,12 @@ bool QSystemSemaphore::isKeyTypeSupported(QNativeIpcKey::Type type)
QNativeIpcKey QSystemSemaphore::platformSafeKey(const QString &key, QNativeIpcKey::Type type)
{
- return { QtIpcCommon::platformSafeKey(key, IpcType::SystemSemaphore, type), type };
+ return QtIpcCommon::platformSafeKey(key, IpcType::SystemSemaphore, type);
}
QNativeIpcKey QSystemSemaphore::legacyNativeKey(const QString &key, QNativeIpcKey::Type type)
{
- return { legacyPlatformSafeKey(key, IpcType::SystemSemaphore, type), type };
+ return QtIpcCommon::legacyPlatformSafeKey(key, IpcType::SystemSemaphore, type);
}
QT_END_NAMESPACE
diff --git a/src/corelib/ipc/qsystemsemaphore.h b/src/corelib/ipc/qsystemsemaphore.h
index bd0057e6b7..df6fd28342 100644
--- a/src/corelib/ipc/qsystemsemaphore.h
+++ b/src/corelib/ipc/qsystemsemaphore.h
@@ -47,14 +47,9 @@ public:
{ setNativeKey({ key, type }, initialValue, mode); }
QNativeIpcKey nativeIpcKey() const;
-#if QT_DEPRECATED_SINCE(6, 10)
- QT_DEPRECATED_VERSION_X_6_10("Please refer to 'Native IPC Key' documentation")
QSystemSemaphore(const QString &key, int initialValue = 0, AccessMode mode = Open);
- QT_DEPRECATED_VERSION_X_6_10("Please refer to 'Native IPC Key' documentation")
void setKey(const QString &key, int initialValue = 0, AccessMode mode = Open);
- QT_DEPRECATED_VERSION_X_6_10("Please refer to 'Native IPC Key' documentation")
QString key() const;
-#endif
bool acquire();
bool release(int n = 1);
diff --git a/src/corelib/ipc/qsystemsemaphore_p.h b/src/corelib/ipc/qsystemsemaphore_p.h
index f63315ee81..788c4fb784 100644
--- a/src/corelib/ipc/qsystemsemaphore_p.h
+++ b/src/corelib/ipc/qsystemsemaphore_p.h
@@ -142,8 +142,6 @@ public:
{
return visit([&](auto p) { return p->modifySemaphore(this, count); });
}
-
- QString legacyKey; // deprecated
};
QT_END_NAMESPACE
diff --git a/src/corelib/ipc/qsystemsemaphore_posix.cpp b/src/corelib/ipc/qsystemsemaphore_posix.cpp
index b290e14de4..7df9593513 100644
--- a/src/corelib/ipc/qsystemsemaphore_posix.cpp
+++ b/src/corelib/ipc/qsystemsemaphore_posix.cpp
@@ -20,9 +20,9 @@
#ifdef Q_OS_UNIX
# include "private/qcore_unix_p.h"
#else
-#define EINTR_LOOP_VAL(var, val, cmd) \
+# define QT_EINTR_LOOP_VAL(var, val, cmd) \
(void)var; var = cmd
-#define EINTR_LOOP(var, cmd) EINTR_LOOP_VAL(var, -1, cmd)
+# define QT_EINTR_LOOP(var, cmd) QT_EINTR_LOOP_VAL(var, -1, cmd)
#endif
// OpenBSD 4.2 doesn't define EIDRM, see BUGS section:
@@ -126,6 +126,12 @@ bool QSystemSemaphorePosix::modifySemaphore(QSystemSemaphorePrivate *self, int c
int cnt = count;
do {
if (::sem_post(semaphore) == -1) {
+#if defined(Q_OS_VXWORKS)
+ if (errno == EINVAL) {
+ semaphore = SEM_FAILED;
+ return modifySemaphore(self, cnt);
+ }
+#endif
self->setUnixErrorString("QSystemSemaphore::modifySemaphore (sem_post)"_L1);
#if defined QSYSTEMSEMAPHORE_DEBUG
qDebug("QSystemSemaphorePosix::modify sem_post failed %d %d", count, errno);
@@ -133,7 +139,7 @@ bool QSystemSemaphorePosix::modifySemaphore(QSystemSemaphorePrivate *self, int c
// rollback changes to preserve the SysV semaphore behavior
for ( ; cnt < count; ++cnt) {
int res;
- EINTR_LOOP(res, ::sem_wait(semaphore));
+ QT_EINTR_LOOP(res, ::sem_wait(semaphore));
}
return false;
}
@@ -141,7 +147,7 @@ bool QSystemSemaphorePosix::modifySemaphore(QSystemSemaphorePrivate *self, int c
} while (cnt > 0);
} else {
int res;
- EINTR_LOOP(res, ::sem_wait(semaphore));
+ QT_EINTR_LOOP(res, ::sem_wait(semaphore));
if (res == -1) {
// If the semaphore was removed be nice and create it and then modifySemaphore again
if (errno == EINVAL || errno == EIDRM) {
diff --git a/src/corelib/ipc/qsystemsemaphore_systemv.cpp b/src/corelib/ipc/qsystemsemaphore_systemv.cpp
index cdfa6adfd4..e5d231d1d4 100644
--- a/src/corelib/ipc/qsystemsemaphore_systemv.cpp
+++ b/src/corelib/ipc/qsystemsemaphore_systemv.cpp
@@ -53,6 +53,9 @@ bool QSystemSemaphoreSystemV::runtimeSupportCheck()
*/
key_t QSystemSemaphoreSystemV::handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode)
{
+ if (unix_key != -1)
+ return unix_key; // we already have a semaphore
+
#if defined(Q_OS_DARWIN)
if (qt_apple_isSandboxed()) {
// attempting to use System V semaphores will get us a SIGSYS
@@ -73,9 +76,6 @@ key_t QSystemSemaphoreSystemV::handle(QSystemSemaphorePrivate *self, QSystemSema
return -1;
}
- if (-1 != unix_key)
- return unix_key;
-
// ftok requires that an actual file exists somewhere
int built = QtIpcCommon::createUnixKeyFile(nativeKeyFile);
if (-1 == built) {
@@ -174,7 +174,7 @@ bool QSystemSemaphoreSystemV::modifySemaphore(QSystemSemaphorePrivate *self, int
operation.sem_flg = SEM_UNDO;
int res;
- EINTR_LOOP(res, semop(semaphore, &operation, 1));
+ QT_EINTR_LOOP(res, semop(semaphore, &operation, 1));
if (-1 == res) {
// If the semaphore was removed be nice and create it and then modifySemaphore again
if (errno == EINVAL || errno == EIDRM) {
diff --git a/src/corelib/ipc/qtipccommon.cpp b/src/corelib/ipc/qtipccommon.cpp
index 46a4777104..b2ae9172fa 100644
--- a/src/corelib/ipc/qtipccommon.cpp
+++ b/src/corelib/ipc/qtipccommon.cpp
@@ -7,7 +7,8 @@
#include <qcryptographichash.h>
#include <qstandardpaths.h>
#include <qstringconverter.h>
-#include <private/qurl_p.h>
+#include <qurl.h>
+#include <qurlquery.h>
#if defined(Q_OS_DARWIN)
# include "private/qcore_mac_p.h"
@@ -18,6 +19,8 @@
// by-one bug in the kernel) the usable bytes are only 30.
# define SHM_NAME_MAX 30
# endif
+#elif defined(Q_OS_WINDOWS)
+# include "qt_windows.h"
#endif
#if QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
@@ -91,16 +94,18 @@ static QNativeIpcKey::Type stringToType(QStringView typeString)
Legacy: this exists for compatibility with QSharedMemory and
QSystemSemaphore between 4.4 and 6.6.
- Generate a string from the key which can be any unicode string into
- the subset that the win/unix kernel allows.
-
- On Unix this will be a file name
+ Returns a QNativeIpcKey that contains a platform-safe key using rules
+ similar to QtIpcCommon::platformSafeKey() below, but using an algorithm
+ that is compatible with Qt 4.4 to 6.6. Additionally, the returned
+ QNativeIpcKey will record the input \a key so it can be included in the
+ string form if necessary to pass to other processes.
*/
-QString QtIpcCommon::legacyPlatformSafeKey(const QString &key, QtIpcCommon::IpcType ipcType,
- QNativeIpcKey::Type type)
+QNativeIpcKey QtIpcCommon::legacyPlatformSafeKey(const QString &key, QtIpcCommon::IpcType ipcType,
+ QNativeIpcKey::Type type)
{
+ QNativeIpcKey k(type);
if (key.isEmpty())
- return QString();
+ return k;
QByteArray hex = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1).toHex();
@@ -111,13 +116,16 @@ QString QtIpcCommon::legacyPlatformSafeKey(const QString &key, QtIpcCommon::IpcT
// to be in the form <application group identifier>/<custom identifier>.
// Since we don't know which application group identifier the user wants
// to apply, we instead document that requirement, and use the key directly.
- return key;
+ QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, key, key);
+ } else {
+ // The shared memory name limit on Apple platforms is very low (30 characters),
+ // so we can't use the logic below of combining the prefix, key, and a hash,
+ // to ensure a unique and valid name. Instead we use the first part of the
+ // hash, which should still long enough to avoid collisions in practice.
+ QString native = u'/' + QLatin1StringView(hex).left(SHM_NAME_MAX - 1);
+ QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, native, key);
}
- // The shared memory name limit on Apple platforms is very low (30 characters),
- // so we can't use the logic below of combining the prefix, key, and a hash,
- // to ensure a unique and valid name. Instead we use the first part of the
- // hash, which should still long enough to avoid collisions in practice.
- return u'/' + QLatin1StringView(hex).left(SHM_NAME_MAX - 1);
+ return k;
#endif
}
@@ -141,38 +149,51 @@ QString QtIpcCommon::legacyPlatformSafeKey(const QString &key, QtIpcCommon::IpcT
switch (type) {
case QNativeIpcKey::Type::Windows:
- if (!isIpcSupported(ipcType, QNativeIpcKey::Type::Windows))
- return QString();
- return result;
+ if (isIpcSupported(ipcType, QNativeIpcKey::Type::Windows))
+ QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, result, key);
+ return k;
case QNativeIpcKey::Type::PosixRealtime:
- if (!isIpcSupported(ipcType, QNativeIpcKey::Type::PosixRealtime))
- return QString();
- return result.prepend(u'/');
+ result.prepend(u'/');
+ if (isIpcSupported(ipcType, QNativeIpcKey::Type::PosixRealtime))
+ QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, result, key);
+ return k;
case QNativeIpcKey::Type::SystemV:
break;
}
- if (!isIpcSupported(ipcType, QNativeIpcKey::Type::SystemV))
- return QString();
- return QStandardPaths::writableLocation(QStandardPaths::TempLocation) + u'/' + result;
+ if (isIpcSupported(ipcType, QNativeIpcKey::Type::SystemV)) {
+ result = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + u'/' + result;
+ QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, result, key);
+ }
+ return k;
}
-QString QtIpcCommon::platformSafeKey(const QString &key, QtIpcCommon::IpcType ipcType,
- QNativeIpcKey::Type type)
+/*!
+ \internal
+ Returns a QNativeIpcKey of type \a type, suitable for QSystemSemaphore or
+ QSharedMemory depending on \a ipcType. The returned native key is generated
+ from the Unicode input \a key and is safe for use on for the key type in
+ question in the current OS.
+*/
+QNativeIpcKey QtIpcCommon::platformSafeKey(const QString &key, QtIpcCommon::IpcType ipcType,
+ QNativeIpcKey::Type type)
{
+ QNativeIpcKey k(type);
if (key.isEmpty())
- return key;
+ return k;
switch (type) {
case QNativeIpcKey::Type::PosixRealtime:
- if (!isIpcSupported(ipcType, QNativeIpcKey::Type::PosixRealtime))
- return QString();
+ if (isIpcSupported(ipcType, QNativeIpcKey::Type::PosixRealtime)) {
#ifdef SHM_NAME_MAX
- // The shared memory name limit on Apple platforms is very low (30
- // characters), so we have to cut it down to avoid ENAMETOOLONG. We
- // hope that there won't be too many collisions...
- return u'/' + QStringView(key).left(SHM_NAME_MAX - 1);
+ // The shared memory name limit on Apple platforms is very low (30
+ // characters), so we have to cut it down to avoid ENAMETOOLONG. We
+ // hope that there won't be too many collisions...
+ k.setNativeKey(u'/' + QStringView(key).left(SHM_NAME_MAX - 1));
+#else
+ k.setNativeKey(u'/' + key);
#endif
- return u'/' + key;
+ }
+ return k;
case QNativeIpcKey::Type::Windows:
if (isIpcSupported(ipcType, QNativeIpcKey::Type::Windows)) {
@@ -194,25 +215,27 @@ QString QtIpcCommon::platformSafeKey(const QString &key, QtIpcCommon::IpcType ip
}
QString result = prefix + mid + payload;
-#ifdef MAX_PATH
+#ifdef Q_OS_WINDOWS
result.truncate(MAX_PATH);
#endif
- return result;
+ k.setNativeKey(result);
}
- return QString();
+ return k;
case QNativeIpcKey::Type::SystemV:
break;
}
// System V
- if (!isIpcSupported(ipcType, QNativeIpcKey::Type::SystemV))
- return QString();
- if (key.startsWith(u'/'))
- return key;
-
- QString baseDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
- return baseDir + u'/' + key;
+ if (isIpcSupported(ipcType, QNativeIpcKey::Type::SystemV)) {
+ if (key.startsWith(u'/')) {
+ k.setNativeKey(key);
+ } else {
+ QString baseDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
+ k.setNativeKey(baseDir + u'/' + key);
+ }
+ }
+ return k;
}
/*!
@@ -221,6 +244,8 @@ QString QtIpcCommon::platformSafeKey(const QString &key, QtIpcCommon::IpcType ip
\since 6.6
\brief The QNativeIpcKey class holds a native key used by QSystemSemaphore and QSharedMemory.
+ \compares equality
+
The \l QSharedMemory and \l QSystemSemaphore classes identify their
resource using a system-wide identifier known as a "key". The low-level key
value as well as the key type are encapsulated in Qt using the \l
@@ -343,6 +368,11 @@ QNativeIpcKey::Type QNativeIpcKey::defaultTypeForOs_internal() noexcept
}
#endif
+/*!
+ \fn QNativeIpcKey::QNativeIpcKey() noexcept
+
+ Constructs a QNativeIpcKey object of type \l DefaultTypeForOs with an empty key.
+*/
/*!
\fn QNativeIpcKey::QNativeIpcKey(Type type) noexcept
@@ -360,19 +390,26 @@ QNativeIpcKey::Type QNativeIpcKey::defaultTypeForOs_internal() noexcept
Copies or moves the content of \a other.
*/
-void QNativeIpcKey::copy_internal(const QNativeIpcKey &)
+void QNativeIpcKey::copy_internal(const QNativeIpcKey &other)
{
- Q_UNREACHABLE();
+ d = new QNativeIpcKeyPrivate(*other.d);
}
void QNativeIpcKey::move_internal(QNativeIpcKey &&) noexcept
{
- Q_UNREACHABLE();
+ // inline code already moved properly, nothing for us to do here
}
-QNativeIpcKey &QNativeIpcKey::assign_internal(const QNativeIpcKey &)
+QNativeIpcKey &QNativeIpcKey::assign_internal(const QNativeIpcKey &other)
{
- Q_UNREACHABLE_RETURN(*this);
+ Q_ASSERT(d || other.d); // only 3 cases to handle
+ if (d && !other.d)
+ *d = {};
+ else if (d)
+ *d = *other.d;
+ else
+ d = new QNativeIpcKeyPrivate(*other.d);
+ return *this;
}
/*!
@@ -382,16 +419,22 @@ QNativeIpcKey &QNativeIpcKey::assign_internal(const QNativeIpcKey &)
*/
void QNativeIpcKey::destroy_internal() noexcept
{
- Q_ASSERT(isSlowPath());
- Q_UNREACHABLE();
+ delete d;
}
/*!
\fn QNativeIpcKey::swap(QNativeIpcKey &other) noexcept
- \fn swap(QNativeIpcKey &lhs, QNativeIpcKey &rhs) noexcept
- Swaps the native IPC key and type \a other with this object, or \a lhs with
- \a rhs. This operation is very fast and never fails.
+ Swaps the native IPC key and type \a other with this object.
+ This operation is very fast and never fails.
+*/
+
+/*!
+ \fn swap(QNativeIpcKey &value1, QNativeIpcKey &value2) noexcept
+ \relates QNativeIpcKey
+
+ Swaps the native IPC key and type \a value1 with \a value2.
+ This operation is very fast and never fails.
*/
/*!
@@ -422,11 +465,6 @@ void QNativeIpcKey::destroy_internal() noexcept
\sa nativeKey(), setType()
*/
-QNativeIpcKey::Type QNativeIpcKey::type_internal() const noexcept
-{
- Q_ASSERT(isSlowPath());
- Q_UNREACHABLE_RETURN({});
-}
/*!
\fn QNativeIpcKey::setType(Type type)
@@ -435,9 +473,9 @@ QNativeIpcKey::Type QNativeIpcKey::type_internal() const noexcept
\sa type(), setNativeKey()
*/
-void QNativeIpcKey::setType_internal(Type)
+void QNativeIpcKey::setType_internal(Type type)
{
- Q_UNREACHABLE();
+ Q_UNUSED(type);
}
/*!
@@ -455,6 +493,28 @@ void QNativeIpcKey::setType_internal(Type)
\sa nativeKey(), setType()
*/
+void QNativeIpcKey::setNativeKey_internal(const QString &)
+{
+ d->legacyKey_.clear();
+}
+
+/*!
+ \fn size_t QNativeIpcKey::qHash(const QNativeIpcKey &ipcKey) noexcept
+
+ Returns the hash value for \a ipcKey, using a default seed of \c 0.
+*/
+
+/*!
+ \fn size_t QNativeIpcKey::qHash(const QNativeIpcKey &ipcKey, size_t seed) noexcept
+
+ Returns the hash value for \a ipcKey, using \a seed to seed the calculation.
+*/
+size_t qHash(const QNativeIpcKey &ipcKey, size_t seed) noexcept
+{
+ // by *choice*, we're not including d->legacyKey_ in the hash -- it's
+ // already partially encoded in the key
+ return qHashMulti(seed, ipcKey.key, ipcKey.type());
+}
/*!
\fn bool QNativeIpcKey::operator==(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept
@@ -462,9 +522,9 @@ void QNativeIpcKey::setType_internal(Type)
Returns true if the \a lhs and \a rhs objects hold the same (or different) contents.
*/
-int QNativeIpcKey::compare_internal(const QNativeIpcKey &, const QNativeIpcKey &) noexcept
+int QNativeIpcKey::compare_internal(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept
{
- Q_UNREACHABLE_RETURN(0);
+ return (QNativeIpcKeyPrivate::legacyKey(lhs) == QNativeIpcKeyPrivate::legacyKey(rhs)) ? 0 : 1;
}
/*!
@@ -479,28 +539,27 @@ int QNativeIpcKey::compare_internal(const QNativeIpcKey &, const QNativeIpcKey &
*/
QString QNativeIpcKey::toString() const
{
- Q_ASSERT(!isSlowPath());
- QString prefix = typeToString(typeAndFlags.type);
+ QString prefix = typeToString(type());
if (prefix.isEmpty()) {
Q_ASSERT(prefix.isNull());
return prefix;
}
- prefix += u':';
QString copy = nativeKey();
copy.replace(u'%', "%25"_L1);
if (copy.startsWith("//"_L1))
copy.replace(0, 2, u"/%2F"_s); // ensure it's parsed as a URL path
- const ushort recodeActions[] = {
- '\\' | 0, // decode
- '?' | 0x200, // encode
- '#' | 0x200, // encode
- 0
- };
- if (!qt_urlRecode(prefix, copy, QUrl::DecodeReserved, recodeActions))
- prefix += copy;
- return prefix;
+ QUrl u;
+ u.setScheme(prefix);
+ u.setPath(copy, QUrl::TolerantMode);
+ if (isSlowPath()) {
+ QUrlQuery q;
+ if (!d->legacyKey_.isEmpty())
+ q.addQueryItem(u"legacyKey"_s, QString(d->legacyKey_).replace(u'%', "%25"_L1));
+ u.setQuery(q);
+ }
+ return u.toString(QUrl::DecodeReserved);
}
/*!
@@ -515,14 +574,11 @@ QString QNativeIpcKey::toString() const
*/
QNativeIpcKey QNativeIpcKey::fromString(const QString &text)
{
- // this duplicates QUrlPrivate::parse a little
+ QUrl u(text, QUrl::TolerantMode);
Type invalidType = {};
- qsizetype colon = text.indexOf(u':');
- if (colon < 0)
- return QNativeIpcKey(invalidType);
-
- Type type = stringToType(QStringView(text).left(colon));
- if (type == invalidType)
+ Type type = stringToType(u.scheme());
+ if (type == invalidType || !u.isValid() || !u.userInfo().isEmpty() || !u.host().isEmpty()
+ || u.port() != -1)
return QNativeIpcKey(invalidType);
QNativeIpcKey result(QString(), type);
@@ -530,20 +586,20 @@ QNativeIpcKey QNativeIpcKey::fromString(const QString &text)
return QNativeIpcKey(invalidType);
// decode the payload
- QStringView payload = QStringView(text).sliced(colon + 1);
- if (qsizetype pos = payload.indexOf(u'?'); pos >= 0)
- payload.truncate(pos);
- if (qsizetype pos = payload.indexOf(u'#'); pos >= 0)
- payload.truncate(pos);
-
- // qt_urlRecode requires a two-step decoding for non-ASCII content
- QString nativeKey, intermediate;
- if (qt_urlRecode(intermediate, payload, QUrl::PrettyDecoded))
- payload = intermediate;
- if (!qt_urlRecode(nativeKey, payload, QUrl::FullyDecoded))
- nativeKey = payload.toString();
-
- result.setNativeKey(nativeKey);
+ result.setNativeKey(u.path());
+
+ if (u.hasQuery()) {
+ const QList items = QUrlQuery(u).queryItems();
+ for (const auto &item : items) {
+ if (item.first == u"legacyKey"_s) {
+ QString legacyKey = QUrl::fromPercentEncoding(item.second.toUtf8());
+ QNativeIpcKeyPrivate::setLegacyKey(result, std::move(legacyKey));
+ } else {
+ // unknown query item
+ return QNativeIpcKey(invalidType);
+ }
+ }
+ }
return result;
}
diff --git a/src/corelib/ipc/qtipccommon.h b/src/corelib/ipc/qtipccommon.h
index 7b85c43237..74f30cb6a4 100644
--- a/src/corelib/ipc/qtipccommon.h
+++ b/src/corelib/ipc/qtipccommon.h
@@ -37,27 +37,28 @@ public:
;
static Type legacyDefaultTypeForOs() noexcept;
- explicit constexpr QNativeIpcKey(Type type = DefaultTypeForOs) noexcept
- : d()
+ constexpr QNativeIpcKey() noexcept = default;
+
+ explicit constexpr QNativeIpcKey(Type type) noexcept
+ : typeAndFlags{type}
{
- typeAndFlags.type = type;
}
Q_IMPLICIT QNativeIpcKey(const QString &k, Type type = DefaultTypeForOs)
- : d(), key(k)
+ : key(k), typeAndFlags{type}
{
- typeAndFlags.type = type;
}
QNativeIpcKey(const QNativeIpcKey &other)
- : d(other.d), key(other.key)
+ : d(other.d), key(other.key), typeAndFlags(other.typeAndFlags)
{
if (isSlowPath())
copy_internal(other);
}
QNativeIpcKey(QNativeIpcKey &&other) noexcept
- : d(other.d), key(std::move(other.key))
+ : d(std::exchange(other.d, nullptr)), key(std::move(other.key)),
+ typeAndFlags(std::move(other.typeAndFlags))
{
if (isSlowPath())
move_internal(std::move(other));
@@ -71,34 +72,34 @@ public:
QNativeIpcKey &operator=(const QNativeIpcKey &other)
{
+ typeAndFlags = other.typeAndFlags;
+ key = other.key;
if (isSlowPath() || other.isSlowPath())
return assign_internal(other);
- d = other.d;
- key = other.key;
+ Q_ASSERT(!d);
return *this;
}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QNativeIpcKey)
- void swap(QNativeIpcKey &other)
+ void swap(QNativeIpcKey &other) noexcept
{
- qt_ptr_swap(d, other.d);
+ std::swap(d, other.d);
key.swap(other.key);
+ typeAndFlags.swap(other.typeAndFlags);
}
- bool isEmpty() const
+ bool isEmpty() const noexcept
{
return key.isEmpty();
}
- bool isValid() const
+ bool isValid() const noexcept
{
return type() != Type{};
}
constexpr Type type() const noexcept
{
- if (isSlowPath())
- return type_internal();
return typeAndFlags.type;
}
@@ -110,60 +111,75 @@ public:
}
QString nativeKey() const noexcept
- { return key; }
+ {
+ return key;
+ }
void setNativeKey(const QString &newKey)
- { key = newKey; }
+ {
+ key = newKey;
+ if (isSlowPath())
+ setNativeKey_internal(newKey);
+ }
Q_CORE_EXPORT QString toString() const;
Q_CORE_EXPORT static QNativeIpcKey fromString(const QString &string);
private:
struct TypeAndFlags {
- quint16 isExtended : 1;
- Type type : 15;
- quint16 reserved;
- };
-
- // Bit 0: if set, holds a pointer (with the LSB set); if clear, holds the
- // the TypeAndFlags structure.
- union {
- QNativeIpcKeyPrivate *d = nullptr;
- TypeAndFlags typeAndFlags;
- static_assert(sizeof(typeAndFlags) <= sizeof(d));
+ Type type = DefaultTypeForOs;
+ quint16 reserved1 = {};
+ quint32 reserved2 = {};
+
+ void swap(TypeAndFlags &other) noexcept
+ {
+ std::swap(type, other.type);
+ std::swap(reserved1, other.reserved1);
+ std::swap(reserved2, other.reserved2);
+ }
+
+ friend constexpr bool operator==(const TypeAndFlags &lhs, const TypeAndFlags &rhs) noexcept
+ {
+ return lhs.type == rhs.type &&
+ lhs.reserved1 == rhs.reserved1 &&
+ lhs.reserved2 == rhs.reserved2;
+ }
};
+ QNativeIpcKeyPrivate *d = nullptr;
QString key;
+ TypeAndFlags typeAndFlags;
+ friend class QNativeIpcKeyPrivate;
constexpr bool isSlowPath() const noexcept
- { return Q_UNLIKELY(typeAndFlags.isExtended); }
+ { return Q_UNLIKELY(d); }
- friend bool operator==(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept
- {
- if (lhs.key != rhs.key)
- return false;
- if (lhs.d == rhs.d)
- return true;
- if (lhs.isSlowPath() && rhs.isSlowPath())
- return compare_internal(lhs, rhs) == 0;
- return lhs.d == rhs.d;
- }
- friend bool operator!=(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept
- {
- return !(lhs == rhs);
- }
+ friend Q_CORE_EXPORT size_t qHash(const QNativeIpcKey &ipcKey, size_t seed) noexcept;
+ friend size_t qHash(const QNativeIpcKey &ipcKey) noexcept
+ { return qHash(ipcKey, 0); }
Q_CORE_EXPORT void copy_internal(const QNativeIpcKey &other);
Q_CORE_EXPORT void move_internal(QNativeIpcKey &&other) noexcept;
Q_CORE_EXPORT QNativeIpcKey &assign_internal(const QNativeIpcKey &other);
Q_CORE_EXPORT void destroy_internal() noexcept;
- Q_DECL_PURE_FUNCTION Q_CORE_EXPORT Type type_internal() const noexcept;
Q_CORE_EXPORT void setType_internal(Type);
+ Q_CORE_EXPORT void setNativeKey_internal(const QString &);
Q_DECL_PURE_FUNCTION Q_CORE_EXPORT static int
compare_internal(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept;
#ifdef Q_OS_DARWIN
Q_DECL_CONST_FUNCTION Q_CORE_EXPORT static Type defaultTypeForOs_internal() noexcept;
#endif
+ friend bool comparesEqual(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept
+ {
+ if (!(lhs.typeAndFlags == rhs.typeAndFlags))
+ return false;
+ if (lhs.key != rhs.key)
+ return false;
+ if (lhs.d == rhs.d)
+ return true;
+ return compare_internal(lhs, rhs) == 0;
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QNativeIpcKey)
};
// not a shared type, exactly, but this works too
@@ -182,8 +198,9 @@ inline auto QNativeIpcKey::legacyDefaultTypeForOs() noexcept -> Type
#endif
}
+QT_END_NAMESPACE
+
#endif // QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
-QT_END_NAMESPACE
#endif // QNATIVEIPCKEY_H
diff --git a/src/corelib/ipc/qtipccommon_p.h b/src/corelib/ipc/qtipccommon_p.h
index bdcdaabd53..72762c5ba7 100644
--- a/src/corelib/ipc/qtipccommon_p.h
+++ b/src/corelib/ipc/qtipccommon_p.h
@@ -28,6 +28,37 @@
QT_BEGIN_NAMESPACE
+class QNativeIpcKeyPrivate
+{
+public:
+ QString legacyKey_;
+
+ static QString legacyKey(const QNativeIpcKey &key)
+ {
+ if (key.isSlowPath())
+ return key.d->legacyKey_;
+ return QString();
+ }
+ static void setLegacyKey(QNativeIpcKey &key, const QString &legacyKey)
+ {
+ QNativeIpcKeyPrivate::makeExtended(key)->legacyKey_ = legacyKey;
+ }
+ static void setNativeAndLegacyKeys(QNativeIpcKey &key, const QString &nativeKey,
+ const QString &legacyKey)
+ {
+ key.setNativeKey(nativeKey);
+ setLegacyKey(key, legacyKey);
+ }
+
+private:
+ static QNativeIpcKeyPrivate *makeExtended(QNativeIpcKey &key)
+ {
+ if (!key.isSlowPath())
+ key.d = new QNativeIpcKeyPrivate;
+ return key.d;
+ }
+};
+
namespace QtIpcCommon {
enum class IpcType {
SharedMemory,
@@ -113,10 +144,8 @@ public:
}
};
-Q_AUTOTEST_EXPORT QString
-legacyPlatformSafeKey(const QString &key, IpcType ipcType,
- QNativeIpcKey::Type type = QNativeIpcKey::legacyDefaultTypeForOs());
-Q_AUTOTEST_EXPORT QString platformSafeKey(const QString &key, IpcType ipcType, QNativeIpcKey::Type type);
+QNativeIpcKey legacyPlatformSafeKey(const QString &key, IpcType ipcType, QNativeIpcKey::Type type);
+QNativeIpcKey platformSafeKey(const QString &key, IpcType ipcType, QNativeIpcKey::Type type);
#ifdef Q_OS_UNIX
// Convenience function to create the file if needed