Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qsystemsemaphore_systemv.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2022 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qsystemsemaphore.h"
7
8#include <qdebug.h>
9#include <qfile.h>
10#include <qcoreapplication.h>
11
12#if QT_CONFIG(sysv_sem)
13
14#include <sys/types.h>
15#include <sys/ipc.h>
16#include <sys/sem.h>
17#include <fcntl.h>
18#include <errno.h>
19
20#if defined(Q_OS_DARWIN)
21#include "private/qcore_mac_p.h"
22#endif
23
24#include "private/qcore_unix_p.h"
25
26// OpenBSD 4.2 doesn't define EIDRM, see BUGS section:
27// http://www.openbsd.org/cgi-bin/man.cgi?query=semop&manpath=OpenBSD+4.2
28#if defined(Q_OS_OPENBSD) && !defined(EIDRM)
29#define EIDRM EINVAL
30#endif
31
33
34using namespace Qt::StringLiterals;
35
36bool QSystemSemaphoreSystemV::runtimeSupportCheck()
37{
38#if defined(Q_OS_DARWIN)
40 return false;
41#endif
42 static const bool result = []() {
43 (void)semget(IPC_PRIVATE, -1, 0); // this will fail
44 return errno != ENOSYS;
45 }();
46 return result;
47}
48
54key_t QSystemSemaphoreSystemV::handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode)
55{
56 if (unix_key != -1)
57 return unix_key; // we already have a semaphore
58
59#if defined(Q_OS_DARWIN)
61 // attempting to use System V semaphores will get us a SIGSYS
62 self->setError(QSystemSemaphore::PermissionDenied,
63 QSystemSemaphore::tr("%1: System V semaphores are not available for "
64 "sandboxed applications. Please build Qt with "
65 "-feature-ipc_posix")
66 .arg("QSystemSemaphore::handle:"_L1));
67 return -1;
68 }
69#endif
70
71 nativeKeyFile = QFile::encodeName(self->nativeKey.nativeKey());
72 if (nativeKeyFile.isEmpty()) {
73 self->setError(QSystemSemaphore::KeyError,
74 QSystemSemaphore::tr("%1: key is empty")
75 .arg("QSystemSemaphore::handle:"_L1));
76 return -1;
77 }
78
79 // ftok requires that an actual file exists somewhere
80 int built = QtIpcCommon::createUnixKeyFile(nativeKeyFile);
81 if (-1 == built) {
82 self->setError(QSystemSemaphore::KeyError,
83 QSystemSemaphore::tr("%1: unable to make key")
84 .arg("QSystemSemaphore::handle:"_L1));
85
86 return -1;
87 }
88 createdFile = (1 == built);
89
90 // Get the unix key for the created file
91 unix_key = ftok(nativeKeyFile, int(self->nativeKey.type()));
92 if (-1 == unix_key) {
93 self->setError(QSystemSemaphore::KeyError,
94 QSystemSemaphore::tr("%1: ftok failed")
95 .arg("QSystemSemaphore::handle:"_L1));
96 return -1;
97 }
98
99 // Get semaphore
100 semaphore = semget(unix_key, 1, 0600 | IPC_CREAT | IPC_EXCL);
101 if (-1 == semaphore) {
102 if (errno == EEXIST)
103 semaphore = semget(unix_key, 1, 0600 | IPC_CREAT);
104 if (-1 == semaphore) {
105 self->setUnixErrorString("QSystemSemaphore::handle"_L1);
106 cleanHandle(self);
107 return -1;
108 }
109 } else {
110 createdSemaphore = true;
111 // Force cleanup of file, it is possible that it can be left over from a crash
112 createdFile = true;
113 }
114
115 if (mode == QSystemSemaphore::Create) {
116 createdSemaphore = true;
117 createdFile = true;
118 }
119
120 // Created semaphore so initialize its value.
121 if (createdSemaphore && self->initialValue >= 0) {
122 qt_semun init_op;
123 init_op.val = self->initialValue;
124 if (-1 == semctl(semaphore, 0, SETVAL, init_op)) {
125 self->setUnixErrorString("QSystemSemaphore::handle"_L1);
126 cleanHandle(self);
127 return -1;
128 }
129 }
130
131 return unix_key;
132}
133
139void QSystemSemaphoreSystemV::cleanHandle(QSystemSemaphorePrivate *self)
140{
141 unix_key = -1;
142
143 // remove the file if we made it
144 if (createdFile) {
145 unlink(nativeKeyFile.constData());
146 createdFile = false;
147 }
148
149 if (createdSemaphore) {
150 if (-1 != semaphore) {
151 if (-1 == semctl(semaphore, 0, IPC_RMID, 0)) {
152 self->setUnixErrorString("QSystemSemaphore::cleanHandle"_L1);
153#if defined QSYSTEMSEMAPHORE_DEBUG
154 qDebug("QSystemSemaphoreSystemV::cleanHandle semctl failed.");
155#endif
156 }
157 semaphore = -1;
158 }
159 createdSemaphore = false;
160 }
161}
162
166bool QSystemSemaphoreSystemV::modifySemaphore(QSystemSemaphorePrivate *self, int count)
167{
168 if (handle(self, QSystemSemaphore::Open) == -1)
169 return false;
170
171 struct sembuf operation;
172 operation.sem_num = 0;
173 operation.sem_op = count;
174 operation.sem_flg = SEM_UNDO;
175
176 int res;
177 QT_EINTR_LOOP(res, semop(semaphore, &operation, 1));
178 if (-1 == res) {
179 // If the semaphore was removed be nice and create it and then modifySemaphore again
180 if (errno == EINVAL || errno == EIDRM) {
181 semaphore = -1;
182 cleanHandle(self);
183 handle(self, QSystemSemaphore::Open);
184 return modifySemaphore(self, count);
185 }
186 self->setUnixErrorString("QSystemSemaphore::modifySemaphore"_L1);
187#if defined QSYSTEMSEMAPHORE_DEBUG
188 qDebug("QSystemSemaphoreSystemV::modify failed %d %d %d %d %d",
189 count, int(semctl(semaphore, 0, GETVAL)), int(errno), int(EIDRM), int(EINVAL);
190#endif
191 return false;
192 }
193
194 self->clearError();
195 return true;
196}
197
198
200
201#endif // QT_CONFIG(sysv_sem)
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
Definition qfile.h:158
Combined button and popup list for selecting options.
QString self
Definition language.cpp:58
bool qt_apple_isSandboxed()
Definition qcore_mac.mm:499
#define QT_EINTR_LOOP(var, cmd)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
#define qDebug
[1]
Definition qlogging.h:164
GLuint64 GLenum void * handle
GLenum mode
GLenum GLenum GLsizei count
GLuint res
GLuint64EXT * result
[6]
SSL_CTX int void * arg