Skip to content

Commit 0e81f5b

Browse files
bugfixes of TSharedMemory on macos.
1 parent 271c756 commit 0e81f5b

7 files changed

+91
-24
lines changed

src/test/sharedmemory/sharedmemory

32 KB
Binary file not shown.

src/test/sharedmemory/sharedmemory.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ static QByteArray randomString(int length)
3737

3838
void TestSharedMemory::initTestCase()
3939
{
40+
sharedMomory.unlink();
4041
sharedMomory.create(100 * 1024 * 1024);
4142
}
4243

@@ -104,6 +105,14 @@ void TestSharedMemory::test2()
104105
sharedMomory.unlock();
105106
res = sharedMomory.detach();
106107
Q_ASSERT(res);
108+
109+
res = sharedMomory.attach();
110+
Q_ASSERT(res);
111+
res = sharedMomory.lockForRead();
112+
Q_ASSERT(res);
113+
int cmp = strncmp((char *)sharedMomory.data(), string.data(), string.length());
114+
Q_ASSERT(cmp == 0);
115+
sharedMomory.unlock();
107116
}
108117

109118
TF_TEST_MAIN(TestSharedMemory)

src/tsharedmemory.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@ class T_CORE_EXPORT TSharedMemory
3434
struct header_t {
3535
#ifdef Q_OS_LINUX
3636
pthread_rwlock_t rwlock;
37-
uint lockcounter {0};
3837
#endif
38+
uint lockcounter {0};
3939
};
4040

41-
void initRwlock(header_t *header) const;
41+
bool initRwlock(header_t *header) const;
42+
void releaseRwlock(header_t *header) const;
43+
4244

4345
#ifndef Q_OS_WIN
4446
QString _name;

src/tsharedmemory_linux.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ void TSharedMemory::initRwlock(header_t *header) const
2222
}
2323

2424

25+
void TSharedMemory::releaseRwlock(header_t *header) const
26+
{
27+
if (header) {
28+
pthread_rwlock_destroy(&header->rwlock);
29+
}
30+
}
31+
32+
2533
bool TSharedMemory::lockForRead()
2634
{
2735
struct timespec timeout;
@@ -65,6 +73,7 @@ bool TSharedMemory::lockForWrite()
6573
} else {
6674
if (res == ETIMEDOUT && header->lockcounter == cnt) {
6775
// resets rwlock object
76+
releaseRwlock(header);
6877
initRwlock(header);
6978
}
7079
}

src/tsharedmemory_macx.cpp

+60-21
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,29 @@
66
*/
77

88
#include "tsharedmemory.h"
9+
#include <TSystemGlobal>
910
#include <semaphore.h>
1011
#include <fcntl.h> // O_CREAT, O_EXCL
11-
#include <sys/stat.h> // mode constants
12+
#include <sys/stat.h>
13+
#include <time.h>
1214
#include <errno.h>
1315

1416

15-
void TSharedMemory::initRwlock(header_t *) const
17+
static inline QByteArray semaphoreName(const QString &name)
1618
{
17-
const QByteArray SEM_NAME = _name + "_global_lock";
19+
return (name.startsWith("/") ? "" : "/") + name.toLatin1() + "_global_lock";
20+
}
21+
1822

19-
sem_t* sem = sem_open(SEM_NAME.data(), O_CREAT | O_EXCL, 0644, 1);
23+
bool TSharedMemory::initRwlock(header_t *) const
24+
{
25+
sem_t *sem = sem_open(semaphoreName(_name).data(), O_CREAT | O_EXCL, 0644, 1);
2026
if (sem == SEM_FAILED) {
2127
if (errno == EEXIST) {
28+
tSystemError("sem_open semaphore already exists: {}", semaphoreName(_name));
2229
return true;
2330
} else {
24-
tSystemError("sem_open (init) failed: {}", strerror(errno));
31+
tSystemError("sem_open (init) failed: {}", (const char*)strerror(errno));
2532
return false;
2633
}
2734
}
@@ -32,24 +39,58 @@ void TSharedMemory::initRwlock(header_t *) const
3239
}
3340

3441

42+
void TSharedMemory::releaseRwlock(header_t *) const
43+
{
44+
sem_unlink(semaphoreName(_name).data());
45+
}
46+
47+
3548
bool TSharedMemory::lockForRead()
3649
{
37-
const QByteArray SEM_NAME = _name + "_global_lock";
50+
// Use semaphore as a lock mechanism between processes.
51+
// PTHREAD_PROCESS_SHARED attribute is not supported on macos.
52+
53+
sem_t *sem = SEM_FAILED;
54+
header_t *header = (header_t *)_ptr;
55+
uint cnt = header->lockcounter;
56+
57+
auto sem_timedwait = [&](int msecs) {
58+
sem = sem_open(semaphoreName(_name).data(), 0);
59+
if (sem == SEM_FAILED) {
60+
tSystemError("sem_open (lock) failed: {}", (const char*)strerror(errno));
61+
return -1;
62+
}
3863

39-
sem_t* sem = sem_open(SEM_NAME.data(), 0);
40-
if (sem == SEM_FAILED) {
41-
tSystemError("sem_open (lock) failed: {}", strerror(errno));
42-
return false;
64+
auto deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(msecs);
65+
while (std::chrono::steady_clock::now() < deadline) {
66+
if (sem_trywait(sem) < 0) {
67+
if (errno == EAGAIN) {
68+
std::this_thread::sleep_for(std::chrono::milliseconds(20));
69+
continue;
70+
} else {
71+
return -1; // error
72+
}
73+
} else {
74+
header->lockcounter++;
75+
return 0; // lock success
76+
}
77+
}
78+
tSystemError("sem_wait (lock) timed out: {}", semaphoreName(_name));
79+
return 1; // timeout
80+
};
81+
82+
int res;
83+
while ((res = sem_timedwait(1000)) == 1) {
84+
if (header->lockcounter == cnt) { // timeout and same counter
85+
releaseRwlock(header);
86+
initRwlock(header);
87+
}
4388
}
4489

45-
if (sem_wait(sem) < 0) {
46-
tSystemError("sem_wait failed: {}", strerror(errno));
90+
if (sem != SEM_FAILED) {
4791
sem_close(sem);
48-
return false;
4992
}
50-
51-
sem_close(sem);
52-
return true;
93+
return !res;
5394
}
5495

5596

@@ -62,16 +103,14 @@ bool TSharedMemory::lockForWrite()
62103

63104
bool TSharedMemory::unlock()
64105
{
65-
const QByteArray SEM_NAME = _name + "_global_lock";
66-
67-
sem_t* sem = sem_open(SEM_NAME.data(), 0); // 既存を開く
106+
sem_t *sem = sem_open(semaphoreName(_name).data(), 0);
68107
if (sem == SEM_FAILED) {
69-
tSystemError("sem_open (unlock) failed: {}", strerror(errno));
108+
tSystemError("sem_open (unlock) failed: {}", (const char*)strerror(errno));
70109
return false;
71110
}
72111

73112
if (sem_post(sem) < 0) {
74-
tSystemError("sem_post failed: {}", strerror(errno));
113+
tSystemError("sem_post failed: {}", (const char*)strerror(errno));
75114
sem_close(sem);
76115
return false;
77116
}

src/tsharedmemory_qt.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -105,5 +105,11 @@ bool TSharedMemory::unlock()
105105
}
106106

107107

108-
void TSharedMemory::initRwlock(header_t *) const
108+
bool TSharedMemory::initRwlock(header_t *) const
109+
{
110+
return true;
111+
}
112+
113+
114+
void TSharedMemory::releaseRwlock(header_t *) const
109115
{}

src/tsharedmemory_unix.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ bool TSharedMemory::create(size_t size)
8989

9090
void TSharedMemory::unlink()
9191
{
92+
releaseRwlock((header_t *)_ptr);
9293
shm_unlink(qUtf8Printable(_name));
9394
tSystemDebug("SharedMemory unlinked. name:{}", qUtf8Printable(_name));
9495
}
@@ -154,6 +155,7 @@ bool TSharedMemory::detach()
154155

155156
_ptr = nullptr;
156157
_size = 0;
158+
tSystemDebug("SharedMemory detached. name:{}", qUtf8Printable(_name));
157159
return true;
158160
}
159161

0 commit comments

Comments
 (0)