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

View File

@ -17,6 +17,8 @@ class Unit : public TestSuite {
} }
private slots: private slots:
void cleanupTestCase();
void test_acquire(); void test_acquire();
void test_release(); void test_release();
void test_get(); void test_get();
@ -28,6 +30,10 @@ private slots:
handle shm_hd__; handle shm_hd__;
void Unit::cleanupTestCase() {
shm_hd__.release();
}
void Unit::test_acquire() { void Unit::test_acquire() {
QVERIFY(!shm_hd__.valid()); QVERIFY(!shm_hd__.valid());
@ -97,6 +103,10 @@ void Unit::test_mt() {
}.join(); }.join();
QVERIFY(shm_hd__.get() == nullptr); QVERIFY(shm_hd__.get() == nullptr);
QVERIFY(!shm_hd__.valid()); 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 } // internal-linkage