15#if QT_CONFIG(sharedmemory)
16#if QT_CONFIG(sysv_shm)
25#include "private/qcore_unix_p.h"
26#if defined(Q_OS_DARWIN)
27#include "private/qcore_mac_p.h"
32using namespace Qt::StringLiterals;
33using namespace QtIpcCommon;
35bool QSharedMemorySystemV::runtimeSupportCheck()
37#if defined(Q_OS_DARWIN)
38 if (qt_apple_isSandboxed())
41 static const bool result = []() {
42 (
void)shmget(IPC_PRIVATE, ~size_t(0), 0);
43 return errno != ENOSYS;
49inline void QSharedMemorySystemV::updateNativeKeyFile(
const QNativeIpcKey &nativeKey)
51 Q_ASSERT(nativeKeyFile.isEmpty() );
52 if (!nativeKey.nativeKey().isEmpty())
53 nativeKeyFile = QFile::encodeName(nativeKey.nativeKey());
57
58
59
60
61key_t QSharedMemorySystemV::handle(QSharedMemoryPrivate *self)
68 if (nativeKeyFile.isEmpty())
69 updateNativeKeyFile(self->nativeKey);
70 if (nativeKeyFile.isEmpty()) {
71 self->setError(QSharedMemory::KeyError,
72 QSharedMemory::tr(
"%1: key is empty")
73 .arg(
"QSharedMemory::handle:"_L1));
77 unix_key = ftok(nativeKeyFile,
int(self->nativeKey.type()));
79 self->setUnixErrorString(
"QSharedMemory::handle"_L1);
80 nativeKeyFile.clear();
86bool QSharedMemorySystemV::cleanHandle(QSharedMemoryPrivate *self)
92 struct shmid_ds shmid_ds;
93 QByteArray keyfile = std::exchange(nativeKeyFile, QByteArray());
95 int id = shmget(unix_key, 0, 0400);
97 if (shmctl(id, IPC_STAT, &shmid_ds))
98 return errno != EINVAL;
101 if (shmid_ds.shm_nattch != 0)
104 if (shmctl(id, IPC_RMID, &shmid_ds) < 0) {
105 if (errno != EINVAL) {
106 self->setUnixErrorString(
"QSharedMemory::remove"_L1);
112 return unlink(keyfile) == 0;
115bool QSharedMemorySystemV::create(QSharedMemoryPrivate *self, qsizetype size)
118 bool createdFile =
false;
119 updateNativeKeyFile(self->nativeKey);
120 int built = createUnixKeyFile(nativeKeyFile);
122 self->setError(QSharedMemory::KeyError,
123 QSharedMemory::tr(
"%1: unable to make key")
124 .arg(
"QSharedMemory::handle:"_L1));
134 unlink(nativeKeyFile);
139 if (-1 == shmget(unix_key, size_t(size), 0600 | IPC_CREAT | IPC_EXCL)) {
140 const auto function =
"QSharedMemory::create"_L1;
143 self->setError(QSharedMemory::InvalidSize,
144 QSharedMemory::tr(
"%1: system-imposed size restrictions")
145 .arg(
"QSharedMemory::handle"_L1));
148 self->setUnixErrorString(function);
150 if (createdFile && self->error != QSharedMemory::AlreadyExists)
151 unlink(nativeKeyFile);
158bool QSharedMemorySystemV::attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode)
161 int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0400 : 0600));
163 self->setUnixErrorString(
"QSharedMemory::attach (shmget)"_L1);
165 nativeKeyFile.clear();
170 self->memory = shmat(id,
nullptr, (mode == QSharedMemory::ReadOnly ? SHM_RDONLY : 0));
171 if (self->memory == MAP_FAILED) {
172 self->memory =
nullptr;
173 self->setUnixErrorString(
"QSharedMemory::attach (shmat)"_L1);
179 if (!shmctl(id, IPC_STAT, &shmid_ds)) {
180 self->size = (qsizetype)shmid_ds.shm_segsz;
182 self->setUnixErrorString(
"QSharedMemory::attach (shmctl)"_L1);
189bool QSharedMemorySystemV::detach(QSharedMemoryPrivate *self)
192 if (shmdt(self->memory) < 0) {
193 const auto function =
"QSharedMemory::detach"_L1;
196 self->setError(QSharedMemory::NotFound,
197 QSharedMemory::tr(
"%1: not attached").arg(function));
200 self->setUnixErrorString(function);
204 self->memory =
nullptr;
207 return cleanHandle(self);