IPC: split the backend implementations of QSharedMemory...
Into separate classes. This temporarily compiles QSharedMemoryPosix on most Unix systems despite defaulting to SystemV. Change-Id: I12a088d1ae424825abd3fffd171d25efdee8d2de Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
75e73ea7fc
commit
eaa7528baa
@ -508,8 +508,6 @@ qt_internal_extend_target(Core
|
|||||||
)
|
)
|
||||||
|
|
||||||
qt_internal_extend_target(Core CONDITION ANDROID
|
qt_internal_extend_target(Core CONDITION ANDROID
|
||||||
SOURCES
|
|
||||||
ipc/qsharedmemory_android.cpp
|
|
||||||
DEFINES
|
DEFINES
|
||||||
LIBS_SUFFIX="_${ANDROID_ABI}.so" # special case
|
LIBS_SUFFIX="_${ANDROID_ABI}.so" # special case
|
||||||
)
|
)
|
||||||
@ -1137,14 +1135,11 @@ qt_internal_extend_target(Core CONDITION QT_FEATURE_clock_gettime AND UNIX
|
|||||||
WrapRt::WrapRt
|
WrapRt::WrapRt
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_internal_extend_target(Core CONDITION UNIX AND NOT ANDROID
|
qt_internal_extend_target(Core CONDITION UNIX
|
||||||
SOURCES
|
SOURCES
|
||||||
ipc/qsharedmemory_posix.cpp
|
ipc/qsharedmemory_posix.cpp
|
||||||
ipc/qsharedmemory_systemv.cpp
|
ipc/qsharedmemory_systemv.cpp
|
||||||
ipc/qsharedmemory_unix.cpp
|
ipc/qsharedmemory_unix.cpp
|
||||||
)
|
|
||||||
qt_internal_extend_target(Core CONDITION UNIX
|
|
||||||
SOURCES
|
|
||||||
ipc/qsystemsemaphore_posix.cpp
|
ipc/qsystemsemaphore_posix.cpp
|
||||||
ipc/qsystemsemaphore_systemv.cpp
|
ipc/qsystemsemaphore_systemv.cpp
|
||||||
ipc/qsystemsemaphore_unix.cpp
|
ipc/qsystemsemaphore_unix.cpp
|
||||||
|
@ -745,7 +745,7 @@ qt_feature("sharedmemory" PUBLIC
|
|||||||
SECTION "Kernel"
|
SECTION "Kernel"
|
||||||
LABEL "QSharedMemory"
|
LABEL "QSharedMemory"
|
||||||
PURPOSE "Provides access to a shared memory segment."
|
PURPOSE "Provides access to a shared memory segment."
|
||||||
CONDITION ( ANDROID OR WIN32 OR ( NOT VXWORKS AND ( TEST_sysv_shm OR TEST_posix_shm ) ) )
|
CONDITION WIN32 OR TEST_sysv_shm OR TEST_posix_shm
|
||||||
)
|
)
|
||||||
qt_feature_definition("sharedmemory" "QT_NO_SHAREDMEMORY" NEGATE VALUE "1")
|
qt_feature_definition("sharedmemory" "QT_NO_SHAREDMEMORY" NEGATE VALUE "1")
|
||||||
qt_feature("shortcut" PUBLIC
|
qt_feature("shortcut" PUBLIC
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
// Copyright (C) 2012 Collabora Ltd, author <robin.burchell@collabora.co.uk>
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
|
||||||
|
|
||||||
#include "qsharedmemory.h"
|
|
||||||
#include "qsharedmemory_p.h"
|
|
||||||
#include <qdebug.h>
|
|
||||||
|
|
||||||
#if QT_CONFIG(sharedmemory)
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
void QSharedMemoryPrivate::setErrorString(QLatin1StringView function)
|
|
||||||
{
|
|
||||||
Q_UNUSED(function);
|
|
||||||
Q_UNIMPLEMENTED();
|
|
||||||
}
|
|
||||||
|
|
||||||
key_t QSharedMemoryPrivate::handle()
|
|
||||||
{
|
|
||||||
Q_UNIMPLEMENTED();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::cleanHandle()
|
|
||||||
{
|
|
||||||
Q_UNIMPLEMENTED();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::create(qsizetype size)
|
|
||||||
{
|
|
||||||
Q_UNUSED(size);
|
|
||||||
Q_UNIMPLEMENTED();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
|
|
||||||
{
|
|
||||||
Q_UNUSED(mode);
|
|
||||||
Q_UNIMPLEMENTED();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::detach()
|
|
||||||
{
|
|
||||||
Q_UNIMPLEMENTED();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // QT_CONFIG(sharedmemory)
|
|
@ -23,12 +23,17 @@
|
|||||||
#include "qsystemsemaphore.h"
|
#include "qsystemsemaphore.h"
|
||||||
#include "private/qobject_p.h"
|
#include "private/qobject_p.h"
|
||||||
|
|
||||||
#if !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_RTEMS)
|
#if QT_CONFIG(posix_shm)
|
||||||
# include <sys/sem.h>
|
# include <sys/mman.h>
|
||||||
|
#endif
|
||||||
|
#if QT_CONFIG(sysv_shm)
|
||||||
|
# include <sys/shm.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class QSharedMemoryPrivate;
|
||||||
|
|
||||||
#if QT_CONFIG(systemsemaphore)
|
#if QT_CONFIG(systemsemaphore)
|
||||||
/*!
|
/*!
|
||||||
Helper class
|
Helper class
|
||||||
@ -61,6 +66,44 @@ private:
|
|||||||
};
|
};
|
||||||
#endif // QT_CONFIG(systemsemaphore)
|
#endif // QT_CONFIG(systemsemaphore)
|
||||||
|
|
||||||
|
class QSharedMemoryPosix
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool handle(QSharedMemoryPrivate *self);
|
||||||
|
bool cleanHandle(QSharedMemoryPrivate *self);
|
||||||
|
bool create(QSharedMemoryPrivate *self, qsizetype size);
|
||||||
|
bool attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode);
|
||||||
|
bool detach(QSharedMemoryPrivate *self);
|
||||||
|
|
||||||
|
int hand = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QSharedMemorySystemV
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
#if QT_CONFIG(sysv_sem)
|
||||||
|
key_t handle(QSharedMemoryPrivate *self);
|
||||||
|
bool cleanHandle(QSharedMemoryPrivate *self);
|
||||||
|
bool create(QSharedMemoryPrivate *self, qsizetype size);
|
||||||
|
bool attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode);
|
||||||
|
bool detach(QSharedMemoryPrivate *self);
|
||||||
|
|
||||||
|
key_t unix_key = 0;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
class QSharedMemoryWin32
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Qt::HANDLE handle(QSharedMemoryPrivate *self);
|
||||||
|
bool cleanHandle(QSharedMemoryPrivate *self);
|
||||||
|
bool create(QSharedMemoryPrivate *self, qsizetype size);
|
||||||
|
bool attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode);
|
||||||
|
bool detach(QSharedMemoryPrivate *self);
|
||||||
|
|
||||||
|
Qt::HANDLE hand = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
class Q_AUTOTEST_EXPORT QSharedMemoryPrivate : public QObjectPrivate
|
class Q_AUTOTEST_EXPORT QSharedMemoryPrivate : public QObjectPrivate
|
||||||
{
|
{
|
||||||
Q_DECLARE_PUBLIC(QSharedMemory)
|
Q_DECLARE_PUBLIC(QSharedMemory)
|
||||||
@ -70,27 +113,49 @@ public:
|
|||||||
qsizetype size = 0;
|
qsizetype size = 0;
|
||||||
QString key;
|
QString key;
|
||||||
QString nativeKey;
|
QString nativeKey;
|
||||||
QSharedMemory::SharedMemoryError error = QSharedMemory::NoError;
|
|
||||||
QString errorString;
|
QString errorString;
|
||||||
#if QT_CONFIG(systemsemaphore)
|
#if QT_CONFIG(systemsemaphore)
|
||||||
QSystemSemaphore systemSemaphore{QString()};
|
QSystemSemaphore systemSemaphore{QString()};
|
||||||
bool lockedByMe = false;
|
bool lockedByMe = false;
|
||||||
#endif
|
#endif
|
||||||
|
QSharedMemory::SharedMemoryError error = QSharedMemory::NoError;
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#if defined(Q_OS_WIN)
|
||||||
Qt::HANDLE handle();
|
using DefaultBackend = QSharedMemoryWin32;
|
||||||
#elif defined(QT_POSIX_IPC)
|
#elif defined(QT_POSIX_IPC)
|
||||||
int handle();
|
using DefaultBackend = QSharedMemoryPosix;
|
||||||
#else
|
#else
|
||||||
key_t handle();
|
using DefaultBackend = QSharedMemorySystemV;
|
||||||
#endif
|
#endif
|
||||||
bool initKey();
|
DefaultBackend backend;
|
||||||
bool cleanHandle();
|
|
||||||
bool create(qsizetype size);
|
|
||||||
bool attach(QSharedMemory::AccessMode mode);
|
|
||||||
bool detach();
|
|
||||||
|
|
||||||
void setErrorString(QLatin1StringView function);
|
bool initKey();
|
||||||
|
|
||||||
|
bool handle()
|
||||||
|
{
|
||||||
|
return backend.handle(this);
|
||||||
|
}
|
||||||
|
bool cleanHandle()
|
||||||
|
{
|
||||||
|
return backend.cleanHandle(this);
|
||||||
|
}
|
||||||
|
bool create(qsizetype size)
|
||||||
|
{
|
||||||
|
return backend.create(this, size);
|
||||||
|
}
|
||||||
|
bool attach(QSharedMemory::AccessMode mode)
|
||||||
|
{
|
||||||
|
return backend.attach(this, mode);
|
||||||
|
}
|
||||||
|
bool detach()
|
||||||
|
{
|
||||||
|
return backend.detach(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setError(QSharedMemory::SharedMemoryError e, const QString &message)
|
||||||
|
{ error = e; errorString = message; }
|
||||||
|
void setUnixErrorString(QLatin1StringView function);
|
||||||
|
void setWindowsErrorString(QLatin1StringView function);
|
||||||
|
|
||||||
#if QT_CONFIG(systemsemaphore)
|
#if QT_CONFIG(systemsemaphore)
|
||||||
bool tryLocker(QSharedMemoryLocker *locker, const QString &function) {
|
bool tryLocker(QSharedMemoryLocker *locker, const QString &function) {
|
||||||
@ -102,15 +167,6 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // QT_CONFIG(systemsemaphore)
|
#endif // QT_CONFIG(systemsemaphore)
|
||||||
|
|
||||||
private:
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
Qt::HANDLE hand = nullptr;
|
|
||||||
#elif defined(QT_POSIX_IPC)
|
|
||||||
int hand = -1;
|
|
||||||
#else
|
|
||||||
key_t unix_key = 0;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
// Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias Koenig <tobias.koenig@kdab.com>
|
// Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias Koenig <tobias.koenig@kdab.com>
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
#include "qplatformdefs.h"
|
|
||||||
|
|
||||||
#include "qsharedmemory.h"
|
#include "qsharedmemory.h"
|
||||||
#include "qsharedmemory_p.h"
|
#include "qsharedmemory_p.h"
|
||||||
#include "qtipccommon_p.h"
|
#include "qtipccommon_p.h"
|
||||||
@ -12,9 +10,7 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#ifdef QT_POSIX_IPC
|
#if QT_CONFIG(posix_shm)
|
||||||
|
|
||||||
#if QT_CONFIG(sharedmemory)
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -28,20 +24,20 @@ QT_BEGIN_NAMESPACE
|
|||||||
using namespace Qt::StringLiterals;
|
using namespace Qt::StringLiterals;
|
||||||
using namespace QtIpcCommon;
|
using namespace QtIpcCommon;
|
||||||
|
|
||||||
int QSharedMemoryPrivate::handle()
|
bool QSharedMemoryPosix::handle(QSharedMemoryPrivate *self)
|
||||||
{
|
{
|
||||||
// don't allow making handles on empty keys
|
// don't allow making handles on empty keys
|
||||||
const QString safeKey = legacyPlatformSafeKey(key, QtIpcCommon::IpcType::SharedMemory);
|
const QString safeKey = legacyPlatformSafeKey(self->key, IpcType::SharedMemory);
|
||||||
if (safeKey.isEmpty()) {
|
if (safeKey.isEmpty()) {
|
||||||
errorString = QSharedMemory::tr("%1: key is empty").arg("QSharedMemory::handle"_L1);
|
self->setError(QSharedMemory::KeyError,
|
||||||
error = QSharedMemory::KeyError;
|
QSharedMemory::tr("%1: key is empty").arg("QSharedMemory::handle"_L1));
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::cleanHandle()
|
bool QSharedMemoryPosix::cleanHandle(QSharedMemoryPrivate *)
|
||||||
{
|
{
|
||||||
qt_safe_close(hand);
|
qt_safe_close(hand);
|
||||||
hand = -1;
|
hand = -1;
|
||||||
@ -49,12 +45,12 @@ bool QSharedMemoryPrivate::cleanHandle()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::create(qsizetype size)
|
bool QSharedMemoryPosix::create(QSharedMemoryPrivate *self, qsizetype size)
|
||||||
{
|
{
|
||||||
if (!handle())
|
if (!handle(self))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const QByteArray shmName = QFile::encodeName(legacyPlatformSafeKey(key, IpcType::SharedMemory));
|
const QByteArray shmName = QFile::encodeName(legacyPlatformSafeKey(self->key, IpcType::SharedMemory));
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
#ifdef O_CLOEXEC
|
#ifdef O_CLOEXEC
|
||||||
@ -70,11 +66,11 @@ bool QSharedMemoryPrivate::create(qsizetype size)
|
|||||||
const auto function = "QSharedMemory::attach (shm_open)"_L1;
|
const auto function = "QSharedMemory::attach (shm_open)"_L1;
|
||||||
switch (errorNumber) {
|
switch (errorNumber) {
|
||||||
case EINVAL:
|
case EINVAL:
|
||||||
errorString = QSharedMemory::tr("%1: bad name").arg(function);
|
self->setError(QSharedMemory::KeyError,
|
||||||
error = QSharedMemory::KeyError;
|
QSharedMemory::tr("%1: bad name").arg(function));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
setErrorString(function);
|
self->setUnixErrorString(function);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -83,7 +79,7 @@ bool QSharedMemoryPrivate::create(qsizetype size)
|
|||||||
int ret;
|
int ret;
|
||||||
EINTR_LOOP(ret, QT_FTRUNCATE(fd, size));
|
EINTR_LOOP(ret, QT_FTRUNCATE(fd, size));
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
setErrorString("QSharedMemory::create (ftruncate)"_L1);
|
self->setUnixErrorString("QSharedMemory::create (ftruncate)"_L1);
|
||||||
qt_safe_close(fd);
|
qt_safe_close(fd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -93,9 +89,9 @@ bool QSharedMemoryPrivate::create(qsizetype size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
|
bool QSharedMemoryPosix::attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode)
|
||||||
{
|
{
|
||||||
const QByteArray shmName = QFile::encodeName(legacyPlatformSafeKey(key, IpcType::SharedMemory));
|
const QByteArray shmName = QFile::encodeName(legacyPlatformSafeKey(self->key, IpcType::SharedMemory));
|
||||||
|
|
||||||
const int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR);
|
const int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR);
|
||||||
const mode_t omode = (mode == QSharedMemory::ReadOnly ? 0400 : 0600);
|
const mode_t omode = (mode == QSharedMemory::ReadOnly ? 0400 : 0600);
|
||||||
@ -113,11 +109,11 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
|
|||||||
const auto function = "QSharedMemory::attach (shm_open)"_L1;
|
const auto function = "QSharedMemory::attach (shm_open)"_L1;
|
||||||
switch (errorNumber) {
|
switch (errorNumber) {
|
||||||
case EINVAL:
|
case EINVAL:
|
||||||
errorString = QSharedMemory::tr("%1: bad name").arg(function);
|
self->setError(QSharedMemory::KeyError,
|
||||||
error = QSharedMemory::KeyError;
|
QSharedMemory::tr("%1: bad name").arg(function));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
setErrorString(function);
|
self->setUnixErrorString(function);
|
||||||
}
|
}
|
||||||
hand = -1;
|
hand = -1;
|
||||||
return false;
|
return false;
|
||||||
@ -126,20 +122,20 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
|
|||||||
// grab the size
|
// grab the size
|
||||||
QT_STATBUF st;
|
QT_STATBUF st;
|
||||||
if (QT_FSTAT(hand, &st) == -1) {
|
if (QT_FSTAT(hand, &st) == -1) {
|
||||||
setErrorString("QSharedMemory::attach (fstat)"_L1);
|
self->setUnixErrorString("QSharedMemory::attach (fstat)"_L1);
|
||||||
cleanHandle();
|
cleanHandle(self);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
size = qsizetype(st.st_size);
|
self->size = qsizetype(st.st_size);
|
||||||
|
|
||||||
// grab the memory
|
// grab the memory
|
||||||
const int mprot = (mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_READ | PROT_WRITE);
|
const int mprot = (mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_READ | PROT_WRITE);
|
||||||
memory = QT_MMAP(0, size_t(size), mprot, MAP_SHARED, hand, 0);
|
self->memory = QT_MMAP(0, size_t(self->size), mprot, MAP_SHARED, hand, 0);
|
||||||
if (memory == MAP_FAILED || !memory) {
|
if (self->memory == MAP_FAILED || !self->memory) {
|
||||||
setErrorString("QSharedMemory::attach (mmap)"_L1);
|
self->setUnixErrorString("QSharedMemory::attach (mmap)"_L1);
|
||||||
cleanHandle();
|
cleanHandle(self);
|
||||||
memory = 0;
|
self->memory = 0;
|
||||||
size = 0;
|
self->size = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,15 +149,15 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::detach()
|
bool QSharedMemoryPosix::detach(QSharedMemoryPrivate *self)
|
||||||
{
|
{
|
||||||
// detach from the memory segment
|
// detach from the memory segment
|
||||||
if (::munmap(memory, size_t(size)) == -1) {
|
if (::munmap(self->memory, size_t(self->size)) == -1) {
|
||||||
setErrorString("QSharedMemory::detach (munmap)"_L1);
|
self->setUnixErrorString("QSharedMemory::detach (munmap)"_L1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memory = 0;
|
self->memory = 0;
|
||||||
size = 0;
|
self->size = 0;
|
||||||
|
|
||||||
#ifdef Q_OS_QNX
|
#ifdef Q_OS_QNX
|
||||||
// On QNX the st_nlink field of struct stat contains the number of
|
// On QNX the st_nlink field of struct stat contains the number of
|
||||||
@ -177,18 +173,18 @@ bool QSharedMemoryPrivate::detach()
|
|||||||
shm_nattch = st.st_nlink - 2;
|
shm_nattch = st.st_nlink - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanHandle();
|
cleanHandle(self);
|
||||||
|
|
||||||
// if there are no attachments then unlink the shared memory
|
// if there are no attachments then unlink the shared memory
|
||||||
if (shm_nattch == 0) {
|
if (shm_nattch == 0) {
|
||||||
const QByteArray shmName = QFile::encodeName(legacyPlatformSafeKey(key, IpcType::SharedMemory));
|
const QByteArray shmName = QFile::encodeName(legacyPlatformSafeKey(self->key, IpcType::SharedMemory));
|
||||||
if (::shm_unlink(shmName.constData()) == -1 && errno != ENOENT)
|
if (::shm_unlink(shmName.constData()) == -1 && errno != ENOENT)
|
||||||
setErrorString("QSharedMemory::detach (shm_unlink)"_L1);
|
self->setUnixErrorString("QSharedMemory::detach (shm_unlink)"_L1);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// On non-QNX systems (tested Linux and Haiku), the st_nlink field is always 1,
|
// On non-QNX systems (tested Linux and Haiku), the st_nlink field is always 1,
|
||||||
// so we'll simply leak the shared memory files.
|
// so we'll simply leak the shared memory files.
|
||||||
cleanHandle();
|
cleanHandle(self);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -196,6 +192,4 @@ bool QSharedMemoryPrivate::detach()
|
|||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QT_CONFIG(sharedmemory)
|
#endif // QT_CONFIG(posix_shm)
|
||||||
|
|
||||||
#endif // QT_POSIX_IPC
|
|
||||||
|
@ -11,20 +11,16 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#ifndef QT_POSIX_IPC
|
#if QT_CONFIG(sysv_shm)
|
||||||
|
|
||||||
#if QT_CONFIG(sharedmemory)
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ipc.h>
|
#include <sys/ipc.h>
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif // QT_CONFIG(sharedmemory)
|
|
||||||
|
|
||||||
#include "private/qcore_unix_p.h"
|
#include "private/qcore_unix_p.h"
|
||||||
|
|
||||||
#if QT_CONFIG(sharedmemory)
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Qt::StringLiterals;
|
using namespace Qt::StringLiterals;
|
||||||
@ -35,50 +31,54 @@ using namespace QtIpcCommon;
|
|||||||
|
|
||||||
If not already made create the handle used for accessing the shared memory.
|
If not already made create the handle used for accessing the shared memory.
|
||||||
*/
|
*/
|
||||||
key_t QSharedMemoryPrivate::handle()
|
key_t QSharedMemorySystemV::handle(QSharedMemoryPrivate *self)
|
||||||
{
|
{
|
||||||
// already made
|
// already made
|
||||||
if (unix_key)
|
if (unix_key)
|
||||||
return unix_key;
|
return unix_key;
|
||||||
|
|
||||||
// don't allow making handles on empty keys
|
// don't allow making handles on empty keys
|
||||||
if (nativeKey.isEmpty()) {
|
if (self->nativeKey.isEmpty()) {
|
||||||
errorString = QSharedMemory::tr("%1: key is empty").arg("QSharedMemory::handle:"_L1);
|
self->setError(QSharedMemory::KeyError,
|
||||||
error = QSharedMemory::KeyError;
|
QSharedMemory::tr("%1: key is empty")
|
||||||
|
.arg("QSharedMemory::handle:"_L1));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ftok requires that an actual file exists somewhere
|
// ftok requires that an actual file exists somewhere
|
||||||
if (!QFile::exists(nativeKey)) {
|
if (!QFile::exists(self->nativeKey)) {
|
||||||
errorString = QSharedMemory::tr("%1: UNIX key file doesn't exist").arg("QSharedMemory::handle:"_L1);
|
self->setError(QSharedMemory::NotFound,
|
||||||
error = QSharedMemory::NotFound;
|
QSharedMemory::tr("%1: UNIX key file doesn't exist")
|
||||||
|
.arg("QSharedMemory::handle:"_L1));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unix_key = ftok(QFile::encodeName(nativeKey).constData(), 'Q');
|
unix_key = ftok(QFile::encodeName(self->nativeKey).constData(), 'Q');
|
||||||
if (-1 == unix_key) {
|
if (-1 == unix_key) {
|
||||||
errorString = QSharedMemory::tr("%1: ftok failed").arg("QSharedMemory::handle:"_L1);
|
self->setError(QSharedMemory::KeyError,
|
||||||
error = QSharedMemory::KeyError;
|
QSharedMemory::tr("%1: ftok failed")
|
||||||
|
.arg("QSharedMemory::handle:"_L1));
|
||||||
unix_key = 0;
|
unix_key = 0;
|
||||||
}
|
}
|
||||||
return unix_key;
|
return unix_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::cleanHandle()
|
bool QSharedMemorySystemV::cleanHandle(QSharedMemoryPrivate *)
|
||||||
{
|
{
|
||||||
unix_key = 0;
|
unix_key = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::create(qsizetype size)
|
bool QSharedMemorySystemV::create(QSharedMemoryPrivate *self, qsizetype size)
|
||||||
{
|
{
|
||||||
// build file if needed
|
// build file if needed
|
||||||
bool createdFile = false;
|
bool createdFile = false;
|
||||||
QByteArray nativeKeyFile = QFile::encodeName(nativeKey);
|
QByteArray nativeKeyFile = QFile::encodeName(self->nativeKey);
|
||||||
int built = createUnixKeyFile(nativeKeyFile);
|
int built = createUnixKeyFile(nativeKeyFile);
|
||||||
if (built == -1) {
|
if (built == -1) {
|
||||||
errorString = QSharedMemory::tr("%1: unable to make key").arg("QSharedMemory::handle:"_L1);
|
self->setError(QSharedMemory::KeyError,
|
||||||
error = QSharedMemory::KeyError;
|
QSharedMemory::tr("%1: unable to make key")
|
||||||
|
.arg("QSharedMemory::handle:"_L1));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (built == 1) {
|
if (built == 1) {
|
||||||
@ -86,7 +86,7 @@ bool QSharedMemoryPrivate::create(qsizetype size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get handle
|
// get handle
|
||||||
if (!handle()) {
|
if (!handle(self)) {
|
||||||
if (createdFile)
|
if (createdFile)
|
||||||
unlink(nativeKeyFile);
|
unlink(nativeKeyFile);
|
||||||
return false;
|
return false;
|
||||||
@ -97,13 +97,14 @@ bool QSharedMemoryPrivate::create(qsizetype size)
|
|||||||
const auto function = "QSharedMemory::create"_L1;
|
const auto function = "QSharedMemory::create"_L1;
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EINVAL:
|
case EINVAL:
|
||||||
errorString = QSharedMemory::tr("%1: system-imposed size restrictions").arg("QSharedMemory::handle"_L1);
|
self->setError(QSharedMemory::InvalidSize,
|
||||||
error = QSharedMemory::InvalidSize;
|
QSharedMemory::tr("%1: system-imposed size restrictions")
|
||||||
|
.arg("QSharedMemory::handle"_L1));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
setErrorString(function);
|
self->setUnixErrorString(function);
|
||||||
}
|
}
|
||||||
if (createdFile && error != QSharedMemory::AlreadyExists)
|
if (createdFile && self->error != QSharedMemory::AlreadyExists)
|
||||||
unlink(nativeKeyFile);
|
unlink(nativeKeyFile);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -111,56 +112,56 @@ bool QSharedMemoryPrivate::create(qsizetype size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
|
bool QSharedMemorySystemV::attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode)
|
||||||
{
|
{
|
||||||
// grab the shared memory segment id
|
// grab the shared memory segment id
|
||||||
int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0400 : 0600));
|
int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0400 : 0600));
|
||||||
if (-1 == id) {
|
if (-1 == id) {
|
||||||
setErrorString("QSharedMemory::attach (shmget)"_L1);
|
self->setUnixErrorString("QSharedMemory::attach (shmget)"_L1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// grab the memory
|
// grab the memory
|
||||||
memory = shmat(id, nullptr, (mode == QSharedMemory::ReadOnly ? SHM_RDONLY : 0));
|
self->memory = shmat(id, nullptr, (mode == QSharedMemory::ReadOnly ? SHM_RDONLY : 0));
|
||||||
if ((void *)-1 == memory) {
|
if (self->memory == MAP_FAILED) {
|
||||||
memory = nullptr;
|
self->memory = nullptr;
|
||||||
setErrorString("QSharedMemory::attach (shmat)"_L1);
|
self->setUnixErrorString("QSharedMemory::attach (shmat)"_L1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// grab the size
|
// grab the size
|
||||||
shmid_ds shmid_ds;
|
shmid_ds shmid_ds;
|
||||||
if (!shmctl(id, IPC_STAT, &shmid_ds)) {
|
if (!shmctl(id, IPC_STAT, &shmid_ds)) {
|
||||||
size = (qsizetype)shmid_ds.shm_segsz;
|
self->size = (qsizetype)shmid_ds.shm_segsz;
|
||||||
} else {
|
} else {
|
||||||
setErrorString("QSharedMemory::attach (shmctl)"_L1);
|
self->setUnixErrorString("QSharedMemory::attach (shmctl)"_L1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::detach()
|
bool QSharedMemorySystemV::detach(QSharedMemoryPrivate *self)
|
||||||
{
|
{
|
||||||
// detach from the memory segment
|
// detach from the memory segment
|
||||||
if (-1 == shmdt(memory)) {
|
if (shmdt(self->memory) < 0) {
|
||||||
const auto function = "QSharedMemory::detach"_L1;
|
const auto function = "QSharedMemory::detach"_L1;
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EINVAL:
|
case EINVAL:
|
||||||
errorString = QSharedMemory::tr("%1: not attached").arg(function);
|
self->setError(QSharedMemory::NotFound,
|
||||||
error = QSharedMemory::NotFound;
|
QSharedMemory::tr("%1: not attached").arg(function));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
setErrorString(function);
|
self->setUnixErrorString(function);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memory = nullptr;
|
self->memory = nullptr;
|
||||||
size = 0;
|
self->size = 0;
|
||||||
|
|
||||||
// Get the number of current attachments
|
// Get the number of current attachments
|
||||||
int id = shmget(unix_key, 0, 0400);
|
int id = shmget(unix_key, 0, 0400);
|
||||||
cleanHandle();
|
cleanHandle(self);
|
||||||
|
|
||||||
struct shmid_ds shmid_ds;
|
struct shmid_ds shmid_ds;
|
||||||
if (0 != shmctl(id, IPC_STAT, &shmid_ds)) {
|
if (0 != shmctl(id, IPC_STAT, &shmid_ds)) {
|
||||||
@ -175,7 +176,7 @@ bool QSharedMemoryPrivate::detach()
|
|||||||
if (shmid_ds.shm_nattch == 0) {
|
if (shmid_ds.shm_nattch == 0) {
|
||||||
// mark for removal
|
// mark for removal
|
||||||
if (-1 == shmctl(id, IPC_RMID, &shmid_ds)) {
|
if (-1 == shmctl(id, IPC_RMID, &shmid_ds)) {
|
||||||
setErrorString("QSharedMemory::remove"_L1);
|
self->setUnixErrorString("QSharedMemory::remove"_L1);
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EINVAL:
|
case EINVAL:
|
||||||
return true;
|
return true;
|
||||||
@ -185,15 +186,12 @@ bool QSharedMemoryPrivate::detach()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove file
|
// remove file
|
||||||
if (!unlink(QFile::encodeName(nativeKey)))
|
if (!unlink(QFile::encodeName(self->nativeKey)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QT_CONFIG(sharedmemory)
|
#endif // QT_CONFIG(sysv_shm)
|
||||||
|
|
||||||
#endif // QT_POSIX_IPC
|
|
||||||
|
@ -1,34 +1,15 @@
|
|||||||
// Copyright (C) 2016 The Qt Company Ltd.
|
// Copyright (C) 2016 The Qt Company Ltd.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
#include "qplatformdefs.h"
|
|
||||||
|
|
||||||
#include "qsharedmemory.h"
|
#include "qsharedmemory.h"
|
||||||
#include "qsharedmemory_p.h"
|
|
||||||
#include "qsystemsemaphore.h"
|
|
||||||
#include <qdebug.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#if QT_CONFIG(sharedmemory)
|
#if QT_CONFIG(sharedmemory)
|
||||||
#include <sys/types.h>
|
# include "qsharedmemory_p.h"
|
||||||
#ifndef QT_POSIX_IPC
|
# include <errno.h>
|
||||||
#include <sys/ipc.h>
|
|
||||||
#include <sys/shm.h>
|
|
||||||
#else
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#endif
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif // QT_CONFIG(sharedmemory)
|
|
||||||
|
|
||||||
#include "private/qcore_unix_p.h"
|
|
||||||
|
|
||||||
#if QT_CONFIG(sharedmemory)
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
void QSharedMemoryPrivate::setErrorString(QLatin1StringView function)
|
void QSharedMemoryPrivate::setUnixErrorString(QLatin1StringView function)
|
||||||
{
|
{
|
||||||
// EINVAL is handled in functions so they can give better error strings
|
// EINVAL is handled in functions so they can give better error strings
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
|
@ -13,7 +13,7 @@ using namespace Qt::StringLiterals;
|
|||||||
|
|
||||||
#if QT_CONFIG(sharedmemory)
|
#if QT_CONFIG(sharedmemory)
|
||||||
|
|
||||||
void QSharedMemoryPrivate::setErrorString(QLatin1StringView function)
|
void QSharedMemoryPrivate::setWindowsErrorString(QLatin1StringView function)
|
||||||
{
|
{
|
||||||
DWORD windowsError = GetLastError();
|
DWORD windowsError = GetLastError();
|
||||||
if (windowsError == 0)
|
if (windowsError == 0)
|
||||||
@ -49,42 +49,41 @@ void QSharedMemoryPrivate::setErrorString(QLatin1StringView function)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE QSharedMemoryPrivate::handle()
|
HANDLE QSharedMemoryWin32::handle(QSharedMemoryPrivate *self)
|
||||||
{
|
{
|
||||||
if (!hand) {
|
if (!hand) {
|
||||||
const auto function = "QSharedMemory::handle"_L1;
|
const auto function = "QSharedMemory::handle"_L1;
|
||||||
if (nativeKey.isEmpty()) {
|
if (self->nativeKey.isEmpty()) {
|
||||||
error = QSharedMemory::KeyError;
|
self->setError(QSharedMemory::KeyError,
|
||||||
errorString = QSharedMemory::tr("%1: unable to make key").arg(function);
|
QSharedMemory::tr("%1: unable to make key").arg(function));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false,
|
hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false,
|
||||||
reinterpret_cast<const wchar_t *>(nativeKey.utf16()));
|
reinterpret_cast<const wchar_t *>(self->nativeKey.utf16()));
|
||||||
if (!hand) {
|
if (!hand) {
|
||||||
setErrorString(function);
|
self->setWindowsErrorString(function);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hand;
|
return hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::cleanHandle()
|
bool QSharedMemoryWin32::cleanHandle(QSharedMemoryPrivate *)
|
||||||
{
|
{
|
||||||
if (hand != 0 && !CloseHandle(hand)) {
|
if (hand != 0 && !CloseHandle(hand)) {
|
||||||
hand = 0;
|
hand = 0;
|
||||||
setErrorString("QSharedMemory::cleanHandle"_L1);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
hand = 0;
|
hand = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::create(qsizetype size)
|
bool QSharedMemoryWin32::create(QSharedMemoryPrivate *self, qsizetype size)
|
||||||
{
|
{
|
||||||
const auto function = "QSharedMemory::create"_L1;
|
const auto function = "QSharedMemory::create"_L1;
|
||||||
if (nativeKey.isEmpty()) {
|
if (self->nativeKey.isEmpty()) {
|
||||||
error = QSharedMemory::KeyError;
|
self->setError(QSharedMemory::KeyError,
|
||||||
errorString = QSharedMemory::tr("%1: key error").arg(function);
|
QSharedMemory::tr("%1: key error").arg(function));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,50 +95,51 @@ bool QSharedMemoryPrivate::create(qsizetype size)
|
|||||||
high = 0;
|
high = 0;
|
||||||
low = DWORD(size_t(size) & 0xffffffff);
|
low = DWORD(size_t(size) & 0xffffffff);
|
||||||
hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, high, low,
|
hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, high, low,
|
||||||
reinterpret_cast<const wchar_t *>(nativeKey.utf16()));
|
reinterpret_cast<const wchar_t *>(self->nativeKey.utf16()));
|
||||||
setErrorString(function);
|
self->setWindowsErrorString(function);
|
||||||
|
|
||||||
// hand is valid when it already exists unlike unix so explicitly check
|
// hand is valid when it already exists unlike unix so explicitly check
|
||||||
return error != QSharedMemory::AlreadyExists && hand;
|
return self->error != QSharedMemory::AlreadyExists && hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
|
bool QSharedMemoryWin32::attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode)
|
||||||
{
|
{
|
||||||
// Grab a pointer to the memory block
|
// Grab a pointer to the memory block
|
||||||
int permissions = (mode == QSharedMemory::ReadOnly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS);
|
int permissions = (mode == QSharedMemory::ReadOnly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS);
|
||||||
memory = (void *)MapViewOfFile(handle(), permissions, 0, 0, 0);
|
self->memory = (void *)MapViewOfFile(handle(self), permissions, 0, 0, 0);
|
||||||
if (0 == memory) {
|
if (!self->memory) {
|
||||||
setErrorString("QSharedMemory::attach"_L1);
|
self->setWindowsErrorString("QSharedMemory::attach"_L1);
|
||||||
cleanHandle();
|
cleanHandle(self);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab the size of the memory we have been given (a multiple of 4K on windows)
|
// Grab the size of the memory we have been given (a multiple of 4K on windows)
|
||||||
MEMORY_BASIC_INFORMATION info;
|
MEMORY_BASIC_INFORMATION info;
|
||||||
if (!VirtualQuery(memory, &info, sizeof(info))) {
|
if (!VirtualQuery(self->memory, &info, sizeof(info))) {
|
||||||
// Windows doesn't set an error code on this one,
|
// Windows doesn't set an error code on this one,
|
||||||
// it should only be a kernel memory error.
|
// it should only be a kernel memory error.
|
||||||
error = QSharedMemory::UnknownError;
|
self->setError(QSharedMemory::UnknownError,
|
||||||
errorString = QSharedMemory::tr("%1: size query failed").arg("QSharedMemory::attach: "_L1);
|
QSharedMemory::tr("%1: size query failed")
|
||||||
|
.arg("QSharedMemory::attach: "_L1));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
size = qsizetype(info.RegionSize);
|
self->size = qsizetype(info.RegionSize);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QSharedMemoryPrivate::detach()
|
bool QSharedMemoryWin32::detach(QSharedMemoryPrivate *self)
|
||||||
{
|
{
|
||||||
// umap memory
|
// umap memory
|
||||||
if (!UnmapViewOfFile(memory)) {
|
if (!UnmapViewOfFile(self->memory)) {
|
||||||
setErrorString("QSharedMemory::detach"_L1);
|
self->setWindowsErrorString("QSharedMemory::detach"_L1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memory = 0;
|
self->memory = 0;
|
||||||
size = 0;
|
self->size = 0;
|
||||||
|
|
||||||
// close handle
|
// close handle
|
||||||
return cleanHandle();
|
return cleanHandle(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // QT_CONFIG(sharedmemory)
|
#endif // QT_CONFIG(sharedmemory)
|
||||||
|
Loading…
Reference in New Issue
Block a user