From 7e44b2dd4d5326dbb4acdbe27a19c3c0a28829ea Mon Sep 17 00:00:00 2001 From: mutouyun Date: Wed, 16 Jan 2019 13:56:25 +0800 Subject: [PATCH] shm would fail with multi-thread accessing --- src/platform/shm_linux.cpp | 34 +++++++++++++++++++++------------- test/test_shm.cpp | 10 ++++++++++ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/platform/shm_linux.cpp b/src/platform/shm_linux.cpp index 056c200..9ab4763 100644 --- a/src/platform/shm_linux.cpp +++ b/src/platform/shm_linux.cpp @@ -8,8 +8,9 @@ #include #include +#include +#include -#include "tls_pointer.h" #include "memory/resource.hpp" namespace { @@ -24,9 +25,12 @@ constexpr void* mem_of(void* mem) { return static_cast(mem) - 1; } -inline auto& m2h() { - static ipc::tls::pointer> cache; - return *cache.create(); +inline auto* m2h() { + static struct { + std::mutex lc_; + ipc::mem::unordered_map cache_; + } m2h_; + return &m2h_; } } // internal-linkage @@ -38,29 +42,32 @@ 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, - S_IRUSR | S_IWUSR | - S_IRGRP | S_IWGRP | - S_IROTH | S_IWOTH); + 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); if (fd == -1) { return nullptr; } size += sizeof(acc_t); if (::ftruncate(fd, static_cast(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; diff --git a/test/test_shm.cpp b/test/test_shm.cpp index de6d8a3..0535f37 100644 --- a/test/test_shm.cpp +++ b/test/test_shm.cpp @@ -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