Skip to content

Commit

Permalink
IPC: split the backend implementations of QSystemSemaphore...
Browse files Browse the repository at this point in the history
Into separate classes. This temporarily compiles QSystemSemaphorePosix
on most Unix systems despite defaulting to SystemV.

Change-Id: I12a088d1ae424825abd3fffd171d23191fbb6db3
Reviewed-by: Fabian Kosmale <[email protected]>
  • Loading branch information
thiagomacieira committed Jan 22, 2023
1 parent 8b92d5a commit 75e73ea
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 157 deletions.
3 changes: 3 additions & 0 deletions src/corelib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,9 @@ qt_internal_extend_target(Core CONDITION UNIX AND NOT ANDROID
ipc/qsharedmemory_posix.cpp
ipc/qsharedmemory_systemv.cpp
ipc/qsharedmemory_unix.cpp
)
qt_internal_extend_target(Core CONDITION UNIX
SOURCES
ipc/qsystemsemaphore_posix.cpp
ipc/qsystemsemaphore_systemv.cpp
ipc/qsystemsemaphore_unix.cpp
Expand Down
2 changes: 1 addition & 1 deletion src/corelib/configure.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ qt_feature("systemsemaphore" PUBLIC
SECTION "Kernel"
LABEL "QSystemSemaphore"
PURPOSE "Provides a general counting system semaphore."
CONDITION ( NOT INTEGRITY AND NOT VXWORKS AND NOT rtems ) AND ( ANDROID OR WIN32 OR TEST_sysv_sem OR TEST_posix_sem )
CONDITION WIN32 OR TEST_sysv_sem OR TEST_posix_sem
)
qt_feature_definition("systemsemaphore" "QT_NO_SYSTEMSEMAPHORE" NEGATE VALUE "1")
qt_feature("xmlstream" PUBLIC
Expand Down
4 changes: 2 additions & 2 deletions src/corelib/ipc/qsystemsemaphore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,9 @@ void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode m
d->clearError();
#if !defined(Q_OS_WIN) && !defined(QT_POSIX_IPC)
// optimization to not destroy/create the file & semaphore
if (key == d->key && mode == Create && d->createdSemaphore && d->createdFile) {
if (key == d->key && mode == Create && d->backend.createdSemaphore && d->backend.createdFile) {
d->initialValue = initialValue;
d->unix_key = -1;
d->backend.unix_key = -1;
d->handle(mode);
return;
}
Expand Down
41 changes: 0 additions & 41 deletions src/corelib/ipc/qsystemsemaphore_android.cpp

This file was deleted.

97 changes: 70 additions & 27 deletions src/corelib/ipc/qsystemsemaphore_p.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2022 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#ifndef QSYSTEMSEMAPHORE_P_H
Expand All @@ -21,58 +22,100 @@

#include "qcoreapplication.h"
#include "qtipccommon_p.h"
#include "private/qtcore-config_p.h"

#include <sys/types.h>
#ifdef QT_POSIX_IPC
# include <semaphore.h>
#if QT_CONFIG(posix_sem)
# include <semaphore.h>
#endif
#ifndef SEM_FAILED
# define SEM_FAILED nullptr
struct sem_t;
#endif
#if QT_CONFIG(sysv_sem)
# include <sys/sem.h>
#endif

QT_BEGIN_NAMESPACE

class QSystemSemaphorePrivate
class QSystemSemaphorePrivate;

struct QSystemSemaphorePosix
{
bool handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode);
void cleanHandle(QSystemSemaphorePrivate *self);
bool modifySemaphore(QSystemSemaphorePrivate *self, int count);

public:
sem_t *semaphore = SEM_FAILED;
bool createdSemaphore = false;
};

struct QSystemSemaphoreSystemV
{
#if QT_CONFIG(sysv_sem)
key_t handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode);
void cleanHandle(QSystemSemaphorePrivate *self);
bool modifySemaphore(QSystemSemaphorePrivate *self, int count);

key_t unix_key = -1;
int semaphore = -1;
bool createdFile = false;
bool createdSemaphore = false;
#endif
};

struct QSystemSemaphoreWin32
{
//#ifdef Q_OS_WIN32 but there's nothing Windows-specific in the header
Qt::HANDLE handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode);
void cleanHandle(QSystemSemaphorePrivate *self);
bool modifySemaphore(QSystemSemaphorePrivate *self, int count);

Qt::HANDLE semaphore = nullptr;
};

class QSystemSemaphorePrivate
{
public:
QString makeKeyFileName()
{
return QtIpcCommon::legacyPlatformSafeKey(key, QtIpcCommon::IpcType::SystemSemaphore);
}

void setWindowsErrorString(QLatin1StringView function); // Windows only
void setUnixErrorString(QLatin1StringView function);
inline void setError(QSystemSemaphore::SystemSemaphoreError e, const QString &message)
{ error = e; errorString = message; }
inline void clearError()
{ setError(QSystemSemaphore::NoError, QString()); }

#ifdef Q_OS_WIN
Qt::HANDLE handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
void setErrorString(const QString &function);
#elif defined(QT_POSIX_IPC)
bool handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
void setErrorString(const QString &function);
#else
key_t handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
void setErrorString(const QString &function);
#endif
void cleanHandle();
bool modifySemaphore(int count);

QString key;
QString fileName;
QString errorString;
int initialValue;
#ifdef Q_OS_WIN
Qt::HANDLE semaphore = nullptr;
QSystemSemaphore::SystemSemaphoreError error = QSystemSemaphore::NoError;

#if defined(Q_OS_WIN)
using DefaultBackend = QSystemSemaphoreWin32;
#elif defined(QT_POSIX_IPC)
sem_t *semaphore = SEM_FAILED;
bool createdSemaphore = false;
using DefaultBackend = QSystemSemaphorePosix;
#else
key_t unix_key = -1;
int semaphore = -1;
bool createdFile = false;
bool createdSemaphore = false;
using DefaultBackend = QSystemSemaphoreSystemV;
#endif
QString errorString;
QSystemSemaphore::SystemSemaphoreError error = QSystemSemaphore::NoError;
DefaultBackend backend;

void handle(QSystemSemaphore::AccessMode mode)
{
backend.handle(this, mode);
}
void cleanHandle()
{
backend.cleanHandle(this);
}
bool modifySemaphore(int count)
{
return backend.modifySemaphore(this, count);
}
};

QT_END_NAMESPACE
Expand Down
53 changes: 26 additions & 27 deletions src/corelib/ipc/qsystemsemaphore_posix.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (C) 2015 Konstantin Ritt <[email protected]>
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, [email protected], author Tobias Koenig <[email protected]>
// Copyright (C) 2022 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#include "qsystemsemaphore.h"
Expand All @@ -10,9 +11,7 @@
#include <qfile.h>
#include <qcoreapplication.h>

#ifdef QT_POSIX_IPC

#if QT_CONFIG(systemsemaphore)
#if QT_CONFIG(posix_sem)

#include <sys/types.h>
#include <fcntl.h>
Expand All @@ -30,29 +29,30 @@ QT_BEGIN_NAMESPACE

using namespace Qt::StringLiterals;

bool QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
bool QSystemSemaphorePosix::handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode)
{
if (semaphore != SEM_FAILED)
return true; // we already have a semaphore

if (fileName.isEmpty()) {
errorString = QSystemSemaphore::tr("%1: key is empty").arg("QSystemSemaphore::handle"_L1);
error = QSystemSemaphore::KeyError;
if (self->fileName.isEmpty()) {
self->setError(QSystemSemaphore::KeyError,
QSystemSemaphore::tr("%1: key is empty")
.arg("QSystemSemaphore::handle"_L1));
return false;
}

const QByteArray semName = QFile::encodeName(fileName);
const QByteArray semName = QFile::encodeName(self->fileName);

// Always try with O_EXCL so we know whether we created the semaphore.
int oflag = O_CREAT | O_EXCL;
for (int tryNum = 0, maxTries = 1; tryNum < maxTries; ++tryNum) {
do {
semaphore = ::sem_open(semName.constData(), oflag, 0600, initialValue);
semaphore = ::sem_open(semName.constData(), oflag, 0600, self->initialValue);
} while (semaphore == SEM_FAILED && errno == EINTR);
if (semaphore == SEM_FAILED && errno == EEXIST) {
if (mode == QSystemSemaphore::Create) {
if (::sem_unlink(semName.constData()) == -1 && errno != ENOENT) {
setErrorString("QSystemSemaphore::handle (sem_unlink)"_L1);
self->setUnixErrorString("QSystemSemaphore::handle (sem_unlink)"_L1);
return false;
}
// Race condition: the semaphore might be recreated before
Expand All @@ -70,7 +70,7 @@ bool QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
}

if (semaphore == SEM_FAILED) {
setErrorString("QSystemSemaphore::handle"_L1);
self->setUnixErrorString("QSystemSemaphore::handle"_L1);
return false;
}

Expand All @@ -79,11 +79,11 @@ bool QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
return true;
}

void QSystemSemaphorePrivate::cleanHandle()
void QSystemSemaphorePosix::cleanHandle(QSystemSemaphorePrivate *self)
{
if (semaphore != SEM_FAILED) {
if (::sem_close(semaphore) == -1) {
setErrorString("QSystemSemaphore::cleanHandle (sem_close)"_L1);
self->setUnixErrorString("QSystemSemaphore::cleanHandle (sem_close)"_L1);
#if defined QSYSTEMSEMAPHORE_DEBUG
qDebug("QSystemSemaphore::cleanHandle sem_close failed.");
#endif
Expand All @@ -92,28 +92,29 @@ void QSystemSemaphorePrivate::cleanHandle()
}

if (createdSemaphore) {
if (::sem_unlink(QFile::encodeName(fileName).constData()) == -1 && errno != ENOENT) {
setErrorString("QSystemSemaphore::cleanHandle (sem_unlink)"_L1);
if (::sem_unlink(QFile::encodeName(self->fileName).constData()) == -1
&& errno != ENOENT) {
self->setUnixErrorString("QSystemSemaphore::cleanHandle (sem_unlink)"_L1);
#if defined QSYSTEMSEMAPHORE_DEBUG
qDebug("QSystemSemaphore::cleanHandle sem_unlink failed.");
qDebug("QSystemSemaphorePosix::cleanHandle sem_unlink failed.");
#endif
}
createdSemaphore = false;
}
}

bool QSystemSemaphorePrivate::modifySemaphore(int count)
bool QSystemSemaphorePosix::modifySemaphore(QSystemSemaphorePrivate *self, int count)
{
if (!handle())
if (!handle(self, QSystemSemaphore::Open))
return false;

if (count > 0) {
int cnt = count;
do {
if (::sem_post(semaphore) == -1) {
setErrorString("QSystemSemaphore::modifySemaphore (sem_post)"_L1);
self->setUnixErrorString("QSystemSemaphore::modifySemaphore (sem_post)"_L1);
#if defined QSYSTEMSEMAPHORE_DEBUG
qDebug("QSystemSemaphore::modify sem_post failed %d %d", count, errno);
qDebug("QSystemSemaphorePosix::modify sem_post failed %d %d", count, errno);
#endif
// rollback changes to preserve the SysV semaphore behavior
for ( ; cnt < count; ++cnt) {
Expand All @@ -131,22 +132,20 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count)
// If the semaphore was removed be nice and create it and then modifySemaphore again
if (errno == EINVAL || errno == EIDRM) {
semaphore = SEM_FAILED;
return modifySemaphore(count);
return modifySemaphore(self, count);
}
setErrorString("QSystemSemaphore::modifySemaphore (sem_wait)"_L1);
self->setUnixErrorString("QSystemSemaphore::modifySemaphore (sem_wait)"_L1);
#if defined QSYSTEMSEMAPHORE_DEBUG
qDebug("QSystemSemaphore::modify sem_wait failed %d %d", count, errno);
qDebug("QSystemSemaphorePosix::modify sem_wait failed %d %d", count, errno);
#endif
return false;
}
}

clearError();
self->clearError();
return true;
}

QT_END_NAMESPACE

#endif // QT_CONFIG(systemsemaphore)

#endif // QT_POSIX_IPC
#endif // QT_CONFIG(posix_sem)
Loading

0 comments on commit 75e73ea

Please sign in to comment.