shm would fail with multi-thread accessing

This commit is contained in:
mutouyun 2019-01-16 13:56:25 +08:00
parent 219e9375ce
commit 7e44b2dd4d
2 changed files with 31 additions and 13 deletions

View File

@ -8,8 +8,9 @@
#include <atomic>
#include <string>
#include <utility>
#include <mutex>
#include "tls_pointer.h"
#include "memory/resource.hpp"
namespace {
@ -24,9 +25,12 @@ constexpr void* mem_of(void* mem) {
return static_cast<acc_t*>(mem) - 1;
}
inline auto& m2h() {
static ipc::tls::pointer<ipc::mem::unordered_map<void*, std::string>> cache;
return *cache.create();
inline auto* m2h() {
static struct {
std::mutex lc_;
ipc::mem::unordered_map<void*, std::string> cache_;
} m2h_;
return &m2h_;
}
} // internal-linkage
@ -38,8 +42,8 @@ void* acquire(char const * name, std::size_t size) {
if (name == nullptr || name[0] == '\0' || size == 0) {
return nullptr;
}
int fd = ::shm_open((std::string{"__IPC_SHM__"} + name).c_str(),
O_CREAT | O_RDWR,
std::string op_name = std::string{"__IPC_SHM__"} + name;
int fd = ::shm_open(op_name.c_str(), O_CREAT | O_RDWR,
S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH);
@ -49,18 +53,21 @@ void* acquire(char const * name, std::size_t size) {
size += sizeof(acc_t);
if (::ftruncate(fd, static_cast<off_t>(size)) != 0) {
::close(fd);
::shm_unlink(name);
::shm_unlink(op_name.c_str());
return nullptr;
}
void* mem = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
::close(fd);
if (mem == MAP_FAILED) {
::shm_unlink(name);
::shm_unlink(op_name.c_str());
return nullptr;
}
auto acc = acc_of(mem);
acc->fetch_add(1, std::memory_order_release);
m2h().emplace(++acc, name);
{
[[maybe_unused]] auto guard = std::unique_lock { m2h()->lc_ };
m2h()->cache_.emplace(++acc, std::move(op_name));
}
return acc;
}
@ -68,7 +75,8 @@ void release(void* mem, std::size_t size) {
if (mem == nullptr) {
return;
}
auto& cc = m2h();
[[maybe_unused]] auto guard = std::unique_lock { m2h()->lc_ };
auto& cc = m2h()->cache_;
auto it = cc.find(mem);
if (it == cc.end()) {
return;

View File

@ -17,6 +17,8 @@ class Unit : public TestSuite {
}
private slots:
void cleanupTestCase();
void test_acquire();
void test_release();
void test_get();
@ -28,6 +30,10 @@ private slots:
handle shm_hd__;
void Unit::cleanupTestCase() {
shm_hd__.release();
}
void Unit::test_acquire() {
QVERIFY(!shm_hd__.valid());
@ -97,6 +103,10 @@ void Unit::test_mt() {
}.join();
QVERIFY(shm_hd__.get() == nullptr);
QVERIFY(!shm_hd__.valid());
QVERIFY(shm_hd__.acquire("my-test", 1024));
std::uint8_t buf[1024] = {};
QVERIFY(memcmp(shm_hd__.get(), buf, sizeof(buf)) == 0);
}
} // internal-linkage