IPC: add native key support to QSystemSemaphore
And deprecate the non-native key support API. Qt 7 may not even store the old, non-native Qt. Documentation in a new commit, when the dust settles. Change-Id: I12a088d1ae424825abd3fffd171d2b549eeed040 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
510e0914c0
commit
3ae052d3bb
@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||||
|
|
||||||
//! [0]
|
//! [0]
|
||||||
QSystemSemaphore sem("market", 3, QSystemSemaphore::Create);
|
QSystemSemaphore sem(QSystemSemaphore::platformSafeKey("market"), 3, QSystemSemaphore::Create);
|
||||||
// resources available == 3
|
// resources available == 3
|
||||||
sem.acquire(); // resources available == 2
|
sem.acquire(); // resources available == 2
|
||||||
sem.acquire(); // resources available == 1
|
sem.acquire(); // resources available == 1
|
||||||
@ -13,7 +13,7 @@ sem.release(2); // resources available == 3
|
|||||||
|
|
||||||
|
|
||||||
//! [1]
|
//! [1]
|
||||||
QSystemSemaphore sem("market", 5, QSystemSemaphore::Create);
|
QSystemSemaphore sem(QSystemSemaphore::platformSafeKey("market"), 5, QSystemSemaphore::Create);
|
||||||
for (int i = 0; i < 5; ++i) // acquire all 5 resources
|
for (int i = 0; i < 5; ++i) // acquire all 5 resources
|
||||||
sem.acquire();
|
sem.acquire();
|
||||||
sem.release(5); // release the 5 resources
|
sem.release(5); // release the 5 resources
|
||||||
|
@ -12,11 +12,35 @@
|
|||||||
# include <qt_windows.h>
|
# include <qt_windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX_PATH
|
||||||
|
# define MAX_PATH PATH_MAX
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
#if QT_CONFIG(sharedmemory)
|
||||||
|
|
||||||
|
using namespace QtIpcCommon;
|
||||||
using namespace Qt::StringLiterals;
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
#if QT_CONFIG(sharedmemory)
|
#if QT_CONFIG(systemsemaphore)
|
||||||
|
inline QNativeIpcKey QSharedMemoryPrivate::semaphoreNativeKey() const
|
||||||
|
{
|
||||||
|
if (isIpcSupported(IpcType::SharedMemory, QNativeIpcKey::Type::Windows)
|
||||||
|
&& nativeKey.type() == QNativeIpcKey::Type::Windows) {
|
||||||
|
// native keys are plain kernel object names, limited to MAX_PATH
|
||||||
|
auto suffix = "_sem"_L1;
|
||||||
|
QString semkey = nativeKey.nativeKey();
|
||||||
|
semkey.truncate(MAX_PATH - suffix.size() - 1);
|
||||||
|
semkey += suffix;
|
||||||
|
return { semkey, QNativeIpcKey::Type::Windows };
|
||||||
|
}
|
||||||
|
|
||||||
|
// System V and POSIX keys appear to operate in different namespaces, so we
|
||||||
|
// can just use the same native key
|
||||||
|
return nativeKey;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class QSharedMemory
|
\class QSharedMemory
|
||||||
@ -293,8 +317,8 @@ bool QSharedMemoryPrivate::initKey()
|
|||||||
if (!cleanHandle())
|
if (!cleanHandle())
|
||||||
return false;
|
return false;
|
||||||
#if QT_CONFIG(systemsemaphore)
|
#if QT_CONFIG(systemsemaphore)
|
||||||
systemSemaphore.setKey(QString(), 1);
|
systemSemaphore.setNativeKey(QNativeIpcKey(), 1);
|
||||||
systemSemaphore.setKey(key, 1);
|
systemSemaphore.setNativeKey(semaphoreNativeKey(), 1);
|
||||||
if (systemSemaphore.error() != QSystemSemaphore::NoError) {
|
if (systemSemaphore.error() != QSystemSemaphore::NoError) {
|
||||||
QString function = "QSharedMemoryPrivate::initKey"_L1;
|
QString function = "QSharedMemoryPrivate::initKey"_L1;
|
||||||
errorString = QSharedMemory::tr("%1: unable to set key on lock").arg(function);
|
errorString = QSharedMemory::tr("%1: unable to set key on lock").arg(function);
|
||||||
|
@ -115,7 +115,7 @@ public:
|
|||||||
QString nativeKey;
|
QString nativeKey;
|
||||||
QString errorString;
|
QString errorString;
|
||||||
#if QT_CONFIG(systemsemaphore)
|
#if QT_CONFIG(systemsemaphore)
|
||||||
QSystemSemaphore systemSemaphore{QString()};
|
QSystemSemaphore systemSemaphore{ QNativeIpcKey() };
|
||||||
bool lockedByMe = false;
|
bool lockedByMe = false;
|
||||||
#endif
|
#endif
|
||||||
QSharedMemory::SharedMemoryError error = QSharedMemory::NoError;
|
QSharedMemory::SharedMemoryError error = QSharedMemory::NoError;
|
||||||
@ -166,6 +166,7 @@ public:
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
QNativeIpcKey semaphoreNativeKey() const;
|
||||||
#endif // QT_CONFIG(systemsemaphore)
|
#endif // QT_CONFIG(systemsemaphore)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
using namespace QtIpcCommon;
|
||||||
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
#if QT_CONFIG(systemsemaphore)
|
#if QT_CONFIG(systemsemaphore)
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -16,12 +19,10 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
\brief The QSystemSemaphore class provides a general counting system semaphore.
|
\brief The QSystemSemaphore class provides a general counting system semaphore.
|
||||||
|
|
||||||
A semaphore is a generalization of a mutex. While a mutex can be
|
A system semaphore is a generalization of \l QSemaphore. Typically, a
|
||||||
locked only once, a semaphore can be acquired multiple times.
|
semaphore is used to protect a certain number of identical resources.
|
||||||
Typically, a semaphore is used to protect a certain number of
|
|
||||||
identical resources.
|
|
||||||
|
|
||||||
Like its lighter counterpart QSemaphore, a QSystemSemaphore can be
|
Like its lighter counterpart, a QSystemSemaphore can be
|
||||||
accessed from multiple \l {QThread} {threads}. Unlike QSemaphore, a
|
accessed from multiple \l {QThread} {threads}. Unlike QSemaphore, a
|
||||||
QSystemSemaphore can also be accessed from multiple \l {QProcess}
|
QSystemSemaphore can also be accessed from multiple \l {QProcess}
|
||||||
{processes}. This means QSystemSemaphore is a much heavier class, so
|
{processes}. This means QSystemSemaphore is a much heavier class, so
|
||||||
@ -38,66 +39,43 @@ QT_BEGIN_NAMESPACE
|
|||||||
process. The function can also be called with a parameter n > 1,
|
process. The function can also be called with a parameter n > 1,
|
||||||
which releases n resources.
|
which releases n resources.
|
||||||
|
|
||||||
A system semaphore is created with a string key that other processes
|
System semaphores are identified by a key, represented by \l QNativeIpcKey. A
|
||||||
can use to use the same semaphore.
|
key can be created in a cross-platform manner by using platformSafeKey(). A
|
||||||
|
system semaphore is created by the QSystemSemaphore constructor when passed
|
||||||
|
an access mode parameter of AccessMode::Create. Once it is created, other
|
||||||
|
processes may attach to the same semaphore using the same key and an access
|
||||||
|
mode parameter of AccessMode::Open.
|
||||||
|
|
||||||
Example: Create a system semaphore
|
Example: Create a system semaphore
|
||||||
\snippet code/src_corelib_kernel_qsystemsemaphore.cpp 0
|
\snippet code/src_corelib_kernel_qsystemsemaphore.cpp 0
|
||||||
|
|
||||||
A typical application of system semaphores is for controlling access
|
For details on the key types, platform-specific limitations, and
|
||||||
to a circular buffer shared by a producer process and a consumer
|
interoperability with older or non-Qt applications, see the \l{Native IPC
|
||||||
processes.
|
Key} documentation. That includes important information for sandboxed
|
||||||
|
applications on Apple platforms, including all apps obtained via the Apple
|
||||||
|
App Store.
|
||||||
|
|
||||||
\section1 Platform-Specific Behavior
|
\sa Inter-Process Communication, QSharedMemory, QSemaphore
|
||||||
|
|
||||||
When using this class, be aware of the following platform
|
|
||||||
differences:
|
|
||||||
|
|
||||||
\b{Windows:} QSystemSemaphore does not own its underlying system
|
|
||||||
semaphore. Windows owns it. This means that when all instances of
|
|
||||||
QSystemSemaphore for a particular key have been destroyed, either by
|
|
||||||
having their destructors called, or because one or more processes
|
|
||||||
crash, Windows removes the underlying system semaphore.
|
|
||||||
|
|
||||||
\b{Unix:}
|
|
||||||
|
|
||||||
\list
|
|
||||||
\li QSystemSemaphore owns the underlying system semaphore
|
|
||||||
in Unix systems. This means that the last process having an instance of
|
|
||||||
QSystemSemaphore for a particular key must remove the underlying
|
|
||||||
system semaphore in its destructor. If the last process crashes
|
|
||||||
without running the QSystemSemaphore destructor, Unix does not
|
|
||||||
automatically remove the underlying system semaphore, and the
|
|
||||||
semaphore survives the crash. A subsequent process that constructs a
|
|
||||||
QSystemSemaphore with the same key will then be given the existing
|
|
||||||
system semaphore. In that case, if the QSystemSemaphore constructor
|
|
||||||
has specified its \l {QSystemSemaphore::AccessMode} {access mode} as
|
|
||||||
\l {QSystemSemaphore::} {Open}, its initial resource count will not
|
|
||||||
be reset to the one provided but remain set to the value it received
|
|
||||||
in the crashed process. To protect against this, the first process
|
|
||||||
to create a semaphore for a particular key (usually a server), must
|
|
||||||
pass its \l {QSystemSemaphore::AccessMode} {access mode} as \l
|
|
||||||
{QSystemSemaphore::} {Create}, which will force Unix to reset the
|
|
||||||
resource count in the underlying system semaphore.
|
|
||||||
|
|
||||||
\li When a process using QSystemSemaphore terminates for
|
|
||||||
any reason, Unix automatically reverses the effect of all acquire
|
|
||||||
operations that were not released. Thus if the process acquires a
|
|
||||||
resource and then exits without releasing it, Unix will release that
|
|
||||||
resource.
|
|
||||||
|
|
||||||
\endlist
|
|
||||||
|
|
||||||
\b{Apple platforms:} Sandboxed applications (including apps
|
|
||||||
shipped through the Apple App Store) require the key to
|
|
||||||
be in the form \c {<application group identifier>/<custom identifier>},
|
|
||||||
as documented \l {https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24}
|
|
||||||
{here} and \l {https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_application-groups}
|
|
||||||
{here}, and the key length is limited to 30 characters.
|
|
||||||
|
|
||||||
\sa QSharedMemory, QSemaphore
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\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().
|
||||||
|
*/
|
||||||
|
QSystemSemaphore::QSystemSemaphore(const QString &key, int initialValue, AccessMode mode)
|
||||||
|
: QSystemSemaphore(legacyNativeKey(key), initialValue, mode)
|
||||||
|
{
|
||||||
|
d->legacyKey = key;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Requests a system semaphore for the specified \a key. The parameters
|
Requests a system semaphore for the specified \a key. The parameters
|
||||||
\a initialValue and \a mode are used according to the following
|
\a initialValue and \a mode are used according to the following
|
||||||
@ -134,10 +112,10 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
\sa acquire(), key()
|
\sa acquire(), key()
|
||||||
*/
|
*/
|
||||||
QSystemSemaphore::QSystemSemaphore(const QString &key, int initialValue, AccessMode mode)
|
QSystemSemaphore::QSystemSemaphore(const QNativeIpcKey &key, int initialValue, AccessMode mode)
|
||||||
: d(new QSystemSemaphorePrivate)
|
: d(new QSystemSemaphorePrivate)
|
||||||
{
|
{
|
||||||
setKey(key, initialValue, mode);
|
setNativeKey(key, initialValue, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -192,16 +170,25 @@ QSystemSemaphore::~QSystemSemaphore()
|
|||||||
create a new semaphore with the new \a key. The \a initialValue and
|
create a new semaphore with the new \a key. The \a initialValue and
|
||||||
\a mode parameters are as defined for the constructor.
|
\a mode parameters are as defined for the constructor.
|
||||||
|
|
||||||
\sa QSystemSemaphore(), key()
|
This function is useful if the native key was shared from another process.
|
||||||
|
See \l{Native IPC Keys} for more information.
|
||||||
|
|
||||||
|
\sa QSystemSemaphore(), nativeKey()
|
||||||
*/
|
*/
|
||||||
void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode mode)
|
void QSystemSemaphore::setNativeKey(const QNativeIpcKey &key, int initialValue, AccessMode mode)
|
||||||
{
|
{
|
||||||
if (key == d->key && mode == Open)
|
if (key == d->nativeKey && mode == Open)
|
||||||
return;
|
return;
|
||||||
|
if (!isKeyTypeSupported(key.type())) {
|
||||||
|
d->setError(KeyError, tr("%1: unsupported key type")
|
||||||
|
.arg("QSystemSemaphore::setNativeKey"_L1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
d->clearError();
|
d->clearError();
|
||||||
#if !defined(Q_OS_WIN) && !defined(QT_POSIX_IPC)
|
#if !defined(Q_OS_WIN) && !defined(QT_POSIX_IPC)
|
||||||
// optimization to not destroy/create the file & semaphore
|
// optimization to not destroy/create the file & semaphore
|
||||||
if (key == d->key && mode == Create && d->backend.createdSemaphore && d->backend.createdFile) {
|
if (key == d->nativeKey && mode == Create && d->backend.createdSemaphore && d->backend.createdFile) {
|
||||||
d->initialValue = initialValue;
|
d->initialValue = initialValue;
|
||||||
d->backend.unix_key = -1;
|
d->backend.unix_key = -1;
|
||||||
d->handle(mode);
|
d->handle(mode);
|
||||||
@ -209,22 +196,55 @@ void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode m
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
d->cleanHandle();
|
d->cleanHandle();
|
||||||
d->key = key;
|
d->nativeKey = key;
|
||||||
d->initialValue = initialValue;
|
d->initialValue = initialValue;
|
||||||
// cache the file name so it doesn't have to be generated all the time.
|
|
||||||
d->fileName = d->makeKeyFileName();
|
|
||||||
d->handle(mode);
|
d->handle(mode);
|
||||||
|
|
||||||
|
d->legacyKey.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the key assigned to this system semaphore. The key is the
|
Returns the key assigned to this system semaphore. The key is the
|
||||||
name by which the semaphore can be accessed from other processes.
|
name by which the semaphore can be accessed from other processes.
|
||||||
|
|
||||||
|
You can use the native key to access system semaphores that have not been
|
||||||
|
created by Qt, or to grant access to non-Qt applications. See \l{Native IPC
|
||||||
|
Keys} for more information.
|
||||||
|
|
||||||
|
\sa setNativeKey()
|
||||||
|
*/
|
||||||
|
QNativeIpcKey QSystemSemaphore::nativeIpcKey() const
|
||||||
|
{
|
||||||
|
return d->nativeKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\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
|
||||||
|
the semaphore with the old key, then calling the constructor to
|
||||||
|
create a new semaphore with the new \a key. The \a initialValue and
|
||||||
|
\a mode parameters are as defined for the constructor.
|
||||||
|
|
||||||
|
\sa QSystemSemaphore(), key()
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
|
||||||
\sa setKey()
|
\sa setKey()
|
||||||
*/
|
*/
|
||||||
QString QSystemSemaphore::key() const
|
QString QSystemSemaphore::key() const
|
||||||
{
|
{
|
||||||
return d->key;
|
return d->legacyKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -360,6 +380,21 @@ void QSystemSemaphorePrivate::setUnixErrorString(QLatin1StringView function)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QSystemSemaphore::isKeyTypeSupported(QNativeIpcKey::Type type)
|
||||||
|
{
|
||||||
|
return QSystemSemaphorePrivate::DefaultBackend::supports(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
QNativeIpcKey QSystemSemaphore::platformSafeKey(const QString &key, QNativeIpcKey::Type type)
|
||||||
|
{
|
||||||
|
return { QtIpcCommon::platformSafeKey(key, IpcType::SystemSemaphore, type), type };
|
||||||
|
}
|
||||||
|
|
||||||
|
QNativeIpcKey QSystemSemaphore::legacyNativeKey(const QString &key, QNativeIpcKey::Type type)
|
||||||
|
{
|
||||||
|
return { legacyPlatformSafeKey(key, IpcType::SystemSemaphore, type), type };
|
||||||
|
}
|
||||||
|
|
||||||
#endif // QT_CONFIG(systemsemaphore)
|
#endif // QT_CONFIG(systemsemaphore)
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
#define QSYSTEMSEMAPHORE_H
|
#define QSYSTEMSEMAPHORE_H
|
||||||
|
|
||||||
#include <QtCore/qcoreapplication.h>
|
#include <QtCore/qcoreapplication.h>
|
||||||
|
#include <QtCore/qtipccommon.h>
|
||||||
#include <QtCore/qstring.h>
|
#include <QtCore/qstring.h>
|
||||||
#include <QtCore/qscopedpointer.h>
|
#include <QtCore/qscopedpointer.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
||||||
#if QT_CONFIG(systemsemaphore)
|
#if QT_CONFIG(systemsemaphore)
|
||||||
|
|
||||||
class QSystemSemaphorePrivate;
|
class QSystemSemaphorePrivate;
|
||||||
@ -38,11 +38,23 @@ public:
|
|||||||
UnknownError
|
UnknownError
|
||||||
};
|
};
|
||||||
|
|
||||||
QSystemSemaphore(const QString &key, int initialValue = 0, AccessMode mode = Open);
|
QSystemSemaphore(const QNativeIpcKey &key, int initialValue = 0, AccessMode = Open);
|
||||||
~QSystemSemaphore();
|
~QSystemSemaphore();
|
||||||
|
|
||||||
|
void setNativeKey(const QNativeIpcKey &key, int initialValue = 0, AccessMode = Open);
|
||||||
|
void setNativeKey(const QString &key, int initialValue = 0, AccessMode mode = Open,
|
||||||
|
QNativeIpcKey::Type type = QNativeIpcKey::legacyDefaultTypeForOs())
|
||||||
|
{ setNativeKey({ key, type }, initialValue, mode); }
|
||||||
|
QNativeIpcKey nativeIpcKey() const;
|
||||||
|
|
||||||
|
#if QT_DEPRECATED_SINCE(6, 9)
|
||||||
|
QT_DEPRECATED_VERSION_X_6_9("Please refer to 'Native IPC Key' documentation")
|
||||||
|
QSystemSemaphore(const QString &key, int initialValue = 0, AccessMode mode = Open);
|
||||||
|
QT_DEPRECATED_VERSION_X_6_9("Please refer to 'Native IPC Key' documentation")
|
||||||
void setKey(const QString &key, int initialValue = 0, AccessMode mode = Open);
|
void setKey(const QString &key, int initialValue = 0, AccessMode mode = Open);
|
||||||
|
QT_DEPRECATED_VERSION_X_6_9("Please refer to 'Native IPC Key' documentation")
|
||||||
QString key() const;
|
QString key() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool acquire();
|
bool acquire();
|
||||||
bool release(int n = 1);
|
bool release(int n = 1);
|
||||||
@ -50,6 +62,12 @@ public:
|
|||||||
SystemSemaphoreError error() const;
|
SystemSemaphoreError error() const;
|
||||||
QString errorString() const;
|
QString errorString() const;
|
||||||
|
|
||||||
|
static bool isKeyTypeSupported(QNativeIpcKey::Type type) Q_DECL_CONST_FUNCTION;
|
||||||
|
static QNativeIpcKey platformSafeKey(const QString &key,
|
||||||
|
QNativeIpcKey::Type type = QNativeIpcKey::DefaultTypeForOs);
|
||||||
|
static QNativeIpcKey legacyNativeKey(const QString &key,
|
||||||
|
QNativeIpcKey::Type type = QNativeIpcKey::legacyDefaultTypeForOs());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(QSystemSemaphore)
|
Q_DISABLE_COPY(QSystemSemaphore)
|
||||||
QScopedPointer<QSystemSemaphorePrivate> d;
|
QScopedPointer<QSystemSemaphorePrivate> d;
|
||||||
|
@ -42,6 +42,9 @@ class QSystemSemaphorePrivate;
|
|||||||
|
|
||||||
struct QSystemSemaphorePosix
|
struct QSystemSemaphorePosix
|
||||||
{
|
{
|
||||||
|
static bool supports(QNativeIpcKey::Type type)
|
||||||
|
{ return type == QNativeIpcKey::Type::PosixRealtime; }
|
||||||
|
|
||||||
bool handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode);
|
bool handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode);
|
||||||
void cleanHandle(QSystemSemaphorePrivate *self);
|
void cleanHandle(QSystemSemaphorePrivate *self);
|
||||||
bool modifySemaphore(QSystemSemaphorePrivate *self, int count);
|
bool modifySemaphore(QSystemSemaphorePrivate *self, int count);
|
||||||
@ -52,11 +55,15 @@ struct QSystemSemaphorePosix
|
|||||||
|
|
||||||
struct QSystemSemaphoreSystemV
|
struct QSystemSemaphoreSystemV
|
||||||
{
|
{
|
||||||
|
static bool supports(QNativeIpcKey::Type type)
|
||||||
|
{ return quint16(type) <= 0xff; }
|
||||||
|
|
||||||
#if QT_CONFIG(sysv_sem)
|
#if QT_CONFIG(sysv_sem)
|
||||||
key_t handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode);
|
key_t handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode);
|
||||||
void cleanHandle(QSystemSemaphorePrivate *self);
|
void cleanHandle(QSystemSemaphorePrivate *self);
|
||||||
bool modifySemaphore(QSystemSemaphorePrivate *self, int count);
|
bool modifySemaphore(QSystemSemaphorePrivate *self, int count);
|
||||||
|
|
||||||
|
QByteArray nativeKeyFile;
|
||||||
key_t unix_key = -1;
|
key_t unix_key = -1;
|
||||||
int semaphore = -1;
|
int semaphore = -1;
|
||||||
bool createdFile = false;
|
bool createdFile = false;
|
||||||
@ -66,6 +73,9 @@ struct QSystemSemaphoreSystemV
|
|||||||
|
|
||||||
struct QSystemSemaphoreWin32
|
struct QSystemSemaphoreWin32
|
||||||
{
|
{
|
||||||
|
static bool supports(QNativeIpcKey::Type type)
|
||||||
|
{ return type == QNativeIpcKey::Type::Windows; }
|
||||||
|
|
||||||
//#ifdef Q_OS_WIN32 but there's nothing Windows-specific in the header
|
//#ifdef Q_OS_WIN32 but there's nothing Windows-specific in the header
|
||||||
Qt::HANDLE handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode);
|
Qt::HANDLE handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode);
|
||||||
void cleanHandle(QSystemSemaphorePrivate *self);
|
void cleanHandle(QSystemSemaphorePrivate *self);
|
||||||
@ -77,11 +87,6 @@ struct QSystemSemaphoreWin32
|
|||||||
class QSystemSemaphorePrivate
|
class QSystemSemaphorePrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QString makeKeyFileName()
|
|
||||||
{
|
|
||||||
return QtIpcCommon::legacyPlatformSafeKey(key, QtIpcCommon::IpcType::SystemSemaphore);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setWindowsErrorString(QLatin1StringView function); // Windows only
|
void setWindowsErrorString(QLatin1StringView function); // Windows only
|
||||||
void setUnixErrorString(QLatin1StringView function);
|
void setUnixErrorString(QLatin1StringView function);
|
||||||
inline void setError(QSystemSemaphore::SystemSemaphoreError e, const QString &message)
|
inline void setError(QSystemSemaphore::SystemSemaphoreError e, const QString &message)
|
||||||
@ -89,8 +94,7 @@ public:
|
|||||||
inline void clearError()
|
inline void clearError()
|
||||||
{ setError(QSystemSemaphore::NoError, QString()); }
|
{ setError(QSystemSemaphore::NoError, QString()); }
|
||||||
|
|
||||||
QString key;
|
QNativeIpcKey nativeKey;
|
||||||
QString fileName;
|
|
||||||
QString errorString;
|
QString errorString;
|
||||||
int initialValue;
|
int initialValue;
|
||||||
QSystemSemaphore::SystemSemaphoreError error = QSystemSemaphore::NoError;
|
QSystemSemaphore::SystemSemaphoreError error = QSystemSemaphore::NoError;
|
||||||
@ -116,6 +120,8 @@ public:
|
|||||||
{
|
{
|
||||||
return backend.modifySemaphore(this, count);
|
return backend.modifySemaphore(this, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString legacyKey; // deprecated
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -34,15 +34,14 @@ bool QSystemSemaphorePosix::handle(QSystemSemaphorePrivate *self, QSystemSemapho
|
|||||||
if (semaphore != SEM_FAILED)
|
if (semaphore != SEM_FAILED)
|
||||||
return true; // we already have a semaphore
|
return true; // we already have a semaphore
|
||||||
|
|
||||||
if (self->fileName.isEmpty()) {
|
const QByteArray semName = QFile::encodeName(self->nativeKey.nativeKey());
|
||||||
|
if (semName.isEmpty()) {
|
||||||
self->setError(QSystemSemaphore::KeyError,
|
self->setError(QSystemSemaphore::KeyError,
|
||||||
QSystemSemaphore::tr("%1: key is empty")
|
QSystemSemaphore::tr("%1: key is empty")
|
||||||
.arg("QSystemSemaphore::handle"_L1));
|
.arg("QSystemSemaphore::handle"_L1));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray semName = QFile::encodeName(self->fileName);
|
|
||||||
|
|
||||||
// Always try with O_EXCL so we know whether we created the semaphore.
|
// Always try with O_EXCL so we know whether we created the semaphore.
|
||||||
int oflag = O_CREAT | O_EXCL;
|
int oflag = O_CREAT | O_EXCL;
|
||||||
for (int tryNum = 0, maxTries = 1; tryNum < maxTries; ++tryNum) {
|
for (int tryNum = 0, maxTries = 1; tryNum < maxTries; ++tryNum) {
|
||||||
@ -92,8 +91,8 @@ void QSystemSemaphorePosix::cleanHandle(QSystemSemaphorePrivate *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (createdSemaphore) {
|
if (createdSemaphore) {
|
||||||
if (::sem_unlink(QFile::encodeName(self->fileName).constData()) == -1
|
const QByteArray semName = QFile::encodeName(self->nativeKey.nativeKey());
|
||||||
&& errno != ENOENT) {
|
if (::sem_unlink(semName) == -1 && errno != ENOENT) {
|
||||||
self->setUnixErrorString("QSystemSemaphore::cleanHandle (sem_unlink)"_L1);
|
self->setUnixErrorString("QSystemSemaphore::cleanHandle (sem_unlink)"_L1);
|
||||||
#if defined QSYSTEMSEMAPHORE_DEBUG
|
#if defined QSYSTEMSEMAPHORE_DEBUG
|
||||||
qDebug("QSystemSemaphorePosix::cleanHandle sem_unlink failed.");
|
qDebug("QSystemSemaphorePosix::cleanHandle sem_unlink failed.");
|
||||||
|
@ -52,19 +52,19 @@ key_t QSystemSemaphoreSystemV::handle(QSystemSemaphorePrivate *self, QSystemSema
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (self->key.isEmpty()) {
|
nativeKeyFile = QFile::encodeName(self->nativeKey.nativeKey());
|
||||||
|
if (nativeKeyFile.isEmpty()) {
|
||||||
self->setError(QSystemSemaphore::KeyError,
|
self->setError(QSystemSemaphore::KeyError,
|
||||||
QSystemSemaphore::tr("%1: key is empty")
|
QSystemSemaphore::tr("%1: key is empty")
|
||||||
.arg("QSystemSemaphore::handle:"_L1));
|
.arg("QSystemSemaphore::handle:"_L1));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ftok requires that an actual file exists somewhere
|
|
||||||
if (-1 != unix_key)
|
if (-1 != unix_key)
|
||||||
return unix_key;
|
return unix_key;
|
||||||
|
|
||||||
// Create the file needed for ftok
|
// ftok requires that an actual file exists somewhere
|
||||||
int built = QtIpcCommon::createUnixKeyFile(QFile::encodeName(self->fileName));
|
int built = QtIpcCommon::createUnixKeyFile(nativeKeyFile);
|
||||||
if (-1 == built) {
|
if (-1 == built) {
|
||||||
self->setError(QSystemSemaphore::KeyError,
|
self->setError(QSystemSemaphore::KeyError,
|
||||||
QSystemSemaphore::tr("%1: unable to make key")
|
QSystemSemaphore::tr("%1: unable to make key")
|
||||||
@ -75,7 +75,7 @@ key_t QSystemSemaphoreSystemV::handle(QSystemSemaphorePrivate *self, QSystemSema
|
|||||||
createdFile = (1 == built);
|
createdFile = (1 == built);
|
||||||
|
|
||||||
// Get the unix key for the created file
|
// Get the unix key for the created file
|
||||||
unix_key = ftok(QFile::encodeName(self->fileName).constData(), 'Q');
|
unix_key = ftok(nativeKeyFile, int(self->nativeKey.type()));
|
||||||
if (-1 == unix_key) {
|
if (-1 == unix_key) {
|
||||||
self->setError(QSystemSemaphore::KeyError,
|
self->setError(QSystemSemaphore::KeyError,
|
||||||
QSystemSemaphore::tr("%1: ftok failed")
|
QSystemSemaphore::tr("%1: ftok failed")
|
||||||
@ -129,7 +129,7 @@ void QSystemSemaphoreSystemV::cleanHandle(QSystemSemaphorePrivate *self)
|
|||||||
|
|
||||||
// remove the file if we made it
|
// remove the file if we made it
|
||||||
if (createdFile) {
|
if (createdFile) {
|
||||||
QFile::remove(self->fileName);
|
unlink(nativeKeyFile.constData());
|
||||||
createdFile = false;
|
createdFile = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,13 +42,13 @@ void QSystemSemaphorePrivate::setWindowsErrorString(QLatin1StringView function)
|
|||||||
HANDLE QSystemSemaphoreWin32::handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode)
|
HANDLE QSystemSemaphoreWin32::handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode)
|
||||||
{
|
{
|
||||||
// don't allow making handles on empty keys
|
// don't allow making handles on empty keys
|
||||||
if (self->key.isEmpty())
|
if (self->nativeKey.isEmpty())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Create it if it doesn't already exists.
|
// Create it if it doesn't already exists.
|
||||||
if (semaphore == 0) {
|
if (semaphore == 0) {
|
||||||
semaphore = CreateSemaphore(0, self->initialValue, MAXLONG,
|
semaphore = CreateSemaphore(0, self->initialValue, MAXLONG,
|
||||||
reinterpret_cast<const wchar_t*>(self->fileName.utf16()));
|
reinterpret_cast<const wchar_t*>(self->nativeKey.nativeKey().utf16()));
|
||||||
if (semaphore == NULL)
|
if (semaphore == NULL)
|
||||||
self->setWindowsErrorString("QSystemSemaphore::handle"_L1);
|
self->setWindowsErrorString("QSystemSemaphore::handle"_L1);
|
||||||
}
|
}
|
||||||
|
@ -478,7 +478,8 @@ struct RunnerLocker
|
|||||||
{
|
{
|
||||||
runner.release();
|
runner.release();
|
||||||
}
|
}
|
||||||
QSystemSemaphore runner{QStringLiteral("androidtestrunner"), 1, QSystemSemaphore::Open};
|
QSystemSemaphore runner{ QSystemSemaphore::platformSafeKey(u"androidtestrunner"_s),
|
||||||
|
1, QSystemSemaphore::Open };
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QSystemSemaphore>
|
#include <QSystemSemaphore>
|
||||||
|
|
||||||
int acquire(int count = 1)
|
int acquire(const QNativeIpcKey &key, int count = 1)
|
||||||
{
|
{
|
||||||
QSystemSemaphore sem("store");
|
QSystemSemaphore sem(key);
|
||||||
|
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
if (!sem.acquire()) {
|
if (!sem.acquire()) {
|
||||||
@ -20,9 +20,9 @@ int acquire(int count = 1)
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int release()
|
int release(const QNativeIpcKey &key)
|
||||||
{
|
{
|
||||||
QSystemSemaphore sem("store");
|
QSystemSemaphore sem(key);
|
||||||
if (!sem.release()) {
|
if (!sem.release()) {
|
||||||
qWarning() << "Could not release" << sem.key();
|
qWarning() << "Could not release" << sem.key();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@ -31,9 +31,9 @@ int release()
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int acquirerelease()
|
int acquirerelease(const QNativeIpcKey &key)
|
||||||
{
|
{
|
||||||
QSystemSemaphore sem("store");
|
QSystemSemaphore sem(key);
|
||||||
if (!sem.acquire()) {
|
if (!sem.acquire()) {
|
||||||
qWarning() << "Could not acquire" << sem.key();
|
qWarning() << "Could not acquire" << sem.key();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@ -52,11 +52,15 @@ int main(int argc, char *argv[])
|
|||||||
QStringList arguments = app.arguments();
|
QStringList arguments = app.arguments();
|
||||||
// binary name is not used here
|
// binary name is not used here
|
||||||
arguments.takeFirst();
|
arguments.takeFirst();
|
||||||
if (arguments.size() < 1) {
|
if (arguments.size() < 2) {
|
||||||
qWarning("Please call the helper with the function to call as argument");
|
fprintf(stderr,
|
||||||
|
"Usage: %s <acquire|release|acquirerelease> <key> [other args...]\n",
|
||||||
|
argv[0]);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString function = arguments.takeFirst();
|
QString function = arguments.takeFirst();
|
||||||
|
QNativeIpcKey key = QNativeIpcKey::fromString(arguments.takeFirst());
|
||||||
if (function == QLatin1String("acquire")) {
|
if (function == QLatin1String("acquire")) {
|
||||||
int count = 1;
|
int count = 1;
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
@ -64,11 +68,11 @@ int main(int argc, char *argv[])
|
|||||||
count = arguments.takeFirst().toInt(&ok);
|
count = arguments.takeFirst().toInt(&ok);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
count = 1;
|
count = 1;
|
||||||
return acquire(count);
|
return acquire(key, count);
|
||||||
} else if (function == QLatin1String("release")) {
|
} else if (function == QLatin1String("release")) {
|
||||||
return release();
|
return release(key);
|
||||||
} else if (function == QLatin1String("acquirerelease")) {
|
} else if (function == QLatin1String("acquirerelease")) {
|
||||||
return acquirerelease();
|
return acquirerelease(key);
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Unknown function" << function;
|
qWarning() << "Unknown function" << function;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Copyright (C) 2016 The Qt Company Ltd.
|
// Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
// Copyright (C) 2022 Intel Corporation.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include <QTest>
|
#include <QTest>
|
||||||
@ -20,13 +21,21 @@ class tst_QSystemSemaphore : public QObject
|
|||||||
public:
|
public:
|
||||||
tst_QSystemSemaphore();
|
tst_QSystemSemaphore();
|
||||||
|
|
||||||
|
QNativeIpcKey platformSafeKey(const QString &key)
|
||||||
|
{
|
||||||
|
QNativeIpcKey::Type keyType = QNativeIpcKey::DefaultTypeForOs;
|
||||||
|
return QSystemSemaphore::platformSafeKey(key, keyType);
|
||||||
|
}
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void init();
|
void init();
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void key_data();
|
void nativeKey_data();
|
||||||
void key();
|
void nativeKey();
|
||||||
|
void legacyKey_data() { nativeKey_data(); }
|
||||||
|
void legacyKey();
|
||||||
|
|
||||||
void basicacquire();
|
void basicacquire();
|
||||||
void complexacquire();
|
void complexacquire();
|
||||||
@ -37,9 +46,7 @@ private slots:
|
|||||||
void processes_data();
|
void processes_data();
|
||||||
void processes();
|
void processes();
|
||||||
|
|
||||||
#if !defined(Q_OS_WIN) && !defined(QT_POSIX_IPC)
|
|
||||||
void undo();
|
void undo();
|
||||||
#endif
|
|
||||||
void initialValue();
|
void initialValue();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -55,7 +62,8 @@ tst_QSystemSemaphore::tst_QSystemSemaphore()
|
|||||||
|
|
||||||
void tst_QSystemSemaphore::init()
|
void tst_QSystemSemaphore::init()
|
||||||
{
|
{
|
||||||
existingLock = new QSystemSemaphore(EXISTING_SHARE, 1, QSystemSemaphore::Create);
|
QNativeIpcKey key = platformSafeKey(EXISTING_SHARE);
|
||||||
|
existingLock = new QSystemSemaphore(key, 1, QSystemSemaphore::Create);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QSystemSemaphore::cleanup()
|
void tst_QSystemSemaphore::cleanup()
|
||||||
@ -63,7 +71,7 @@ void tst_QSystemSemaphore::cleanup()
|
|||||||
delete existingLock;
|
delete existingLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QSystemSemaphore::key_data()
|
void tst_QSystemSemaphore::nativeKey_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QString>("constructorKey");
|
QTest::addColumn<QString>("constructorKey");
|
||||||
QTest::addColumn<QString>("setKey");
|
QTest::addColumn<QString>("setKey");
|
||||||
@ -76,7 +84,27 @@ void tst_QSystemSemaphore::key_data()
|
|||||||
/*!
|
/*!
|
||||||
Basic key testing
|
Basic key testing
|
||||||
*/
|
*/
|
||||||
void tst_QSystemSemaphore::key()
|
void tst_QSystemSemaphore::nativeKey()
|
||||||
|
{
|
||||||
|
QFETCH(QString, constructorKey);
|
||||||
|
QFETCH(QString, setKey);
|
||||||
|
QNativeIpcKey constructorIpcKey = platformSafeKey(constructorKey);
|
||||||
|
QNativeIpcKey setIpcKey = platformSafeKey(setKey);
|
||||||
|
|
||||||
|
QSystemSemaphore sem(constructorIpcKey);
|
||||||
|
QCOMPARE(sem.nativeIpcKey(), constructorIpcKey);
|
||||||
|
QCOMPARE(sem.error(), QSystemSemaphore::NoError);
|
||||||
|
QCOMPARE(sem.errorString(), QString());
|
||||||
|
|
||||||
|
sem.setNativeKey(setIpcKey);
|
||||||
|
QCOMPARE(sem.nativeIpcKey(), setIpcKey);
|
||||||
|
QCOMPARE(sem.error(), QSystemSemaphore::NoError);
|
||||||
|
QCOMPARE(sem.errorString(), QString());
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_WARNING_PUSH
|
||||||
|
QT_WARNING_DISABLE_DEPRECATED
|
||||||
|
void tst_QSystemSemaphore::legacyKey()
|
||||||
{
|
{
|
||||||
QFETCH(QString, constructorKey);
|
QFETCH(QString, constructorKey);
|
||||||
QFETCH(QString, setKey);
|
QFETCH(QString, setKey);
|
||||||
@ -91,10 +119,12 @@ void tst_QSystemSemaphore::key()
|
|||||||
QCOMPARE(sem.error(), QSystemSemaphore::NoError);
|
QCOMPARE(sem.error(), QSystemSemaphore::NoError);
|
||||||
QCOMPARE(sem.errorString(), QString());
|
QCOMPARE(sem.errorString(), QString());
|
||||||
}
|
}
|
||||||
|
QT_WARNING_POP
|
||||||
|
|
||||||
void tst_QSystemSemaphore::basicacquire()
|
void tst_QSystemSemaphore::basicacquire()
|
||||||
{
|
{
|
||||||
QSystemSemaphore sem("QSystemSemaphore_basicacquire", 1, QSystemSemaphore::Create);
|
QNativeIpcKey key = platformSafeKey("QSystemSemaphore_basicacquire");
|
||||||
|
QSystemSemaphore sem(key, 1, QSystemSemaphore::Create);
|
||||||
QVERIFY(sem.acquire());
|
QVERIFY(sem.acquire());
|
||||||
QCOMPARE(sem.error(), QSystemSemaphore::NoError);
|
QCOMPARE(sem.error(), QSystemSemaphore::NoError);
|
||||||
QVERIFY(sem.release());
|
QVERIFY(sem.release());
|
||||||
@ -104,7 +134,8 @@ void tst_QSystemSemaphore::basicacquire()
|
|||||||
|
|
||||||
void tst_QSystemSemaphore::complexacquire()
|
void tst_QSystemSemaphore::complexacquire()
|
||||||
{
|
{
|
||||||
QSystemSemaphore sem("QSystemSemaphore_complexacquire", 2, QSystemSemaphore::Create);
|
QNativeIpcKey key = platformSafeKey("QSystemSemaphore_complexacquire");
|
||||||
|
QSystemSemaphore sem(key, 2, QSystemSemaphore::Create);
|
||||||
QVERIFY(sem.acquire());
|
QVERIFY(sem.acquire());
|
||||||
QCOMPARE(sem.error(), QSystemSemaphore::NoError);
|
QCOMPARE(sem.error(), QSystemSemaphore::NoError);
|
||||||
QVERIFY(sem.release());
|
QVERIFY(sem.release());
|
||||||
@ -126,7 +157,8 @@ void tst_QSystemSemaphore::complexacquire()
|
|||||||
|
|
||||||
void tst_QSystemSemaphore::release()
|
void tst_QSystemSemaphore::release()
|
||||||
{
|
{
|
||||||
QSystemSemaphore sem("QSystemSemaphore_release", 0, QSystemSemaphore::Create);
|
QNativeIpcKey key = platformSafeKey("QSystemSemaphore_release");
|
||||||
|
QSystemSemaphore sem(key, 0, QSystemSemaphore::Create);
|
||||||
QVERIFY(sem.release());
|
QVERIFY(sem.release());
|
||||||
QCOMPARE(sem.error(), QSystemSemaphore::NoError);
|
QCOMPARE(sem.error(), QSystemSemaphore::NoError);
|
||||||
QVERIFY(sem.release());
|
QVERIFY(sem.release());
|
||||||
@ -147,7 +179,8 @@ void tst_QSystemSemaphore::basicProcesses()
|
|||||||
#if !QT_CONFIG(process)
|
#if !QT_CONFIG(process)
|
||||||
QSKIP("No qprocess support", SkipAll);
|
QSKIP("No qprocess support", SkipAll);
|
||||||
#else
|
#else
|
||||||
QSystemSemaphore sem("store", 0, QSystemSemaphore::Create);
|
QNativeIpcKey key = platformSafeKey("store");
|
||||||
|
QSystemSemaphore sem(key, 0, QSystemSemaphore::Create);
|
||||||
|
|
||||||
QProcess acquire;
|
QProcess acquire;
|
||||||
acquire.setProcessChannelMode(QProcess::ForwardedChannels);
|
acquire.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||||
@ -155,12 +188,12 @@ void tst_QSystemSemaphore::basicProcesses()
|
|||||||
QProcess release;
|
QProcess release;
|
||||||
release.setProcessChannelMode(QProcess::ForwardedChannels);
|
release.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||||
|
|
||||||
acquire.start(m_helperBinary, QStringList("acquire"));
|
acquire.start(m_helperBinary, { "acquire", key.toString() });
|
||||||
QVERIFY2(acquire.waitForStarted(), "Could not start helper binary");
|
QVERIFY2(acquire.waitForStarted(), "Could not start helper binary");
|
||||||
acquire.waitForFinished(HELPERWAITTIME);
|
acquire.waitForFinished(HELPERWAITTIME);
|
||||||
QCOMPARE(acquire.state(), QProcess::Running);
|
QCOMPARE(acquire.state(), QProcess::Running);
|
||||||
acquire.kill();
|
acquire.kill();
|
||||||
release.start(m_helperBinary, QStringList("release"));
|
release.start(m_helperBinary, { "release", key.toString() });
|
||||||
QVERIFY2(release.waitForStarted(), "Could not start helper binary");
|
QVERIFY2(release.waitForStarted(), "Could not start helper binary");
|
||||||
acquire.waitForFinished(HELPERWAITTIME);
|
acquire.waitForFinished(HELPERWAITTIME);
|
||||||
release.waitForFinished(HELPERWAITTIME);
|
release.waitForFinished(HELPERWAITTIME);
|
||||||
@ -183,7 +216,8 @@ void tst_QSystemSemaphore::processes()
|
|||||||
#if !QT_CONFIG(process)
|
#if !QT_CONFIG(process)
|
||||||
QSKIP("No qprocess support", SkipAll);
|
QSKIP("No qprocess support", SkipAll);
|
||||||
#else
|
#else
|
||||||
QSystemSemaphore sem("store", 1, QSystemSemaphore::Create);
|
QNativeIpcKey key = platformSafeKey("store");
|
||||||
|
QSystemSemaphore sem(key, 1, QSystemSemaphore::Create);
|
||||||
|
|
||||||
QFETCH(int, processes);
|
QFETCH(int, processes);
|
||||||
QList<QString> scripts(processes, "acquirerelease");
|
QList<QString> scripts(processes, "acquirerelease");
|
||||||
@ -193,7 +227,7 @@ void tst_QSystemSemaphore::processes()
|
|||||||
QProcess *p = new QProcess;
|
QProcess *p = new QProcess;
|
||||||
p->setProcessChannelMode(QProcess::ForwardedChannels);
|
p->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||||
consumers.append(p);
|
consumers.append(p);
|
||||||
p->start(m_helperBinary, QStringList(scripts.at(i)));
|
p->start(m_helperBinary, { scripts.at(i), key.toString() });
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!consumers.isEmpty()) {
|
while (!consumers.isEmpty()) {
|
||||||
@ -205,16 +239,24 @@ void tst_QSystemSemaphore::processes()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test only checks a system v unix behavior.
|
|
||||||
#if !defined(Q_OS_WIN) && !defined(QT_POSIX_IPC)
|
|
||||||
void tst_QSystemSemaphore::undo()
|
void tst_QSystemSemaphore::undo()
|
||||||
{
|
{
|
||||||
#if !QT_CONFIG(process)
|
#if !QT_CONFIG(process)
|
||||||
QSKIP("No qprocess support", SkipAll);
|
QSKIP("No qprocess support", SkipAll);
|
||||||
#else
|
#else
|
||||||
QSystemSemaphore sem("store", 1, QSystemSemaphore::Create);
|
QNativeIpcKey key = platformSafeKey("store");
|
||||||
|
switch (key.type()) {
|
||||||
|
case QNativeIpcKey::Type::PosixRealtime:
|
||||||
|
case QNativeIpcKey::Type::Windows:
|
||||||
|
QSKIP("This test only checks a System V behavior.");
|
||||||
|
|
||||||
QStringList acquireArguments = QStringList("acquire");
|
case QNativeIpcKey::Type::SystemV:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSystemSemaphore sem(key, 1, QSystemSemaphore::Create);
|
||||||
|
|
||||||
|
QStringList acquireArguments = { "acquire", key.toString() };
|
||||||
QProcess acquire;
|
QProcess acquire;
|
||||||
acquire.setProcessChannelMode(QProcess::ForwardedChannels);
|
acquire.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||||
acquire.start(m_helperBinary, acquireArguments);
|
acquire.start(m_helperBinary, acquireArguments);
|
||||||
@ -230,17 +272,17 @@ void tst_QSystemSemaphore::undo()
|
|||||||
QVERIFY(acquire.state()== QProcess::NotRunning);
|
QVERIFY(acquire.state()== QProcess::NotRunning);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void tst_QSystemSemaphore::initialValue()
|
void tst_QSystemSemaphore::initialValue()
|
||||||
{
|
{
|
||||||
#if !QT_CONFIG(process)
|
#if !QT_CONFIG(process)
|
||||||
QSKIP("No qprocess support", SkipAll);
|
QSKIP("No qprocess support", SkipAll);
|
||||||
#else
|
#else
|
||||||
QSystemSemaphore sem("store", 1, QSystemSemaphore::Create);
|
QNativeIpcKey key = platformSafeKey("store");
|
||||||
|
QSystemSemaphore sem(key, 1, QSystemSemaphore::Create);
|
||||||
|
|
||||||
QStringList acquireArguments = QStringList("acquire");
|
QStringList acquireArguments = { "acquire", key.toString() };
|
||||||
QStringList releaseArguments = QStringList("release");
|
QStringList releaseArguments = { "release", key.toString() };
|
||||||
QProcess acquire;
|
QProcess acquire;
|
||||||
acquire.setProcessChannelMode(QProcess::ForwardedChannels);
|
acquire.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user