Skip to content

Commit fafa5e8

Browse files
committedOct 28, 2023
Fixed memory access exception in multithreading.
1 parent c74f78e commit fafa5e8

File tree

5 files changed

+40
-22
lines changed

5 files changed

+40
-22
lines changed
 

‎3rdparty/gtest/src/gtest-death-test.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,8 +1296,8 @@ static void StackLowerThanAddress(const void* ptr, bool* result) {
12961296
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
12971297
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
12981298
static bool StackGrowsDown() {
1299-
int dummy;
1300-
bool result;
1299+
int dummy {};
1300+
bool result {};
13011301
StackLowerThanAddress(&dummy, &result);
13021302
return result;
13031303
}

‎src/libipc/ipc.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ struct chunk_info_t {
182182
auto& chunk_storages() {
183183
class chunk_handle_t {
184184
ipc::unordered_map<ipc::string, ipc::shm::handle> handles_;
185+
std::mutex lock_;
185186

186187
static bool make_handle(ipc::shm::handle &h, ipc::string const &shm_name, std::size_t chunk_size) {
187188
if (!h.valid() &&
@@ -197,19 +198,25 @@ auto& chunk_storages() {
197198
chunk_info_t *get_info(conn_info_head *inf, std::size_t chunk_size) {
198199
ipc::string pref {(inf == nullptr) ? ipc::string{} : inf->prefix_};
199200
ipc::string shm_name {ipc::make_prefix(pref, {"CHUNK_INFO__", ipc::to_string(chunk_size)})};
200-
ipc::shm::handle &h = handles_[pref];
201-
if (!make_handle(h, shm_name, chunk_size)) {
202-
return nullptr;
201+
ipc::shm::handle *h;
202+
{
203+
std::lock_guard<std::mutex> guard {lock_};
204+
h = &(handles_[pref]);
205+
if (!make_handle(*h, shm_name, chunk_size)) {
206+
return nullptr;
207+
}
203208
}
204-
auto *info = static_cast<chunk_info_t*>(h.get());
209+
auto *info = static_cast<chunk_info_t*>(h->get());
205210
if (info == nullptr) {
206211
ipc::error("[chunk_storages] chunk_shm.id_info_.get failed: chunk_size = %zd\n", chunk_size);
207212
return nullptr;
208213
}
209214
return info;
210215
}
211216
};
212-
static ipc::map<std::size_t, chunk_handle_t> chunk_hs;
217+
using deleter_t = void (*)(chunk_handle_t*);
218+
using chunk_handle_ptr_t = std::unique_ptr<chunk_handle_t, deleter_t>;
219+
static ipc::map<std::size_t, chunk_handle_ptr_t> chunk_hs;
213220
return chunk_hs;
214221
}
215222

@@ -220,13 +227,17 @@ chunk_info_t *chunk_storage_info(conn_info_head *inf, std::size_t chunk_size) {
220227
static ipc::rw_lock lock;
221228
IPC_UNUSED_ std::shared_lock<ipc::rw_lock> guard {lock};
222229
if ((it = storages.find(chunk_size)) == storages.end()) {
223-
using chunk_handle_t = std::decay_t<decltype(storages)>::value_type::second_type;
230+
using chunk_handle_ptr_t = std::decay_t<decltype(storages)>::value_type::second_type;
231+
using chunk_handle_t = chunk_handle_ptr_t::element_type;
224232
guard.unlock();
225233
IPC_UNUSED_ std::lock_guard<ipc::rw_lock> guard {lock};
226-
it = storages.emplace(chunk_size, chunk_handle_t{}).first;
234+
it = storages.emplace(chunk_size, chunk_handle_ptr_t{
235+
ipc::mem::alloc<chunk_handle_t>(), [](chunk_handle_t *p) {
236+
ipc::mem::destruct(p);
237+
}}).first;
227238
}
228239
}
229-
return it->second.get_info(inf, chunk_size);
240+
return it->second->get_info(inf, chunk_size);
230241
}
231242

232243
std::pair<ipc::storage_id_t, void*> acquire_storage(conn_info_head *inf, std::size_t size, ipc::circ::cc_t conns) {
@@ -356,8 +367,7 @@ struct queue_generator {
356367
"QU_CONN__",
357368
ipc::to_string(DataSize), "__",
358369
ipc::to_string(AlignSize), "__",
359-
name}).c_str()} {
360-
}
370+
name}).c_str()} {}
361371

362372
void disconnect_receiver() {
363373
bool dis = que_.disconnect();

‎src/libipc/platform/posix/shm_posix.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ id_t acquire(char const * name, std::size_t size, unsigned mode) {
4949
ipc::error("fail acquire: name is empty\n");
5050
return nullptr;
5151
}
52+
// For portable use, a shared memory object should be identified by name of the form /somename.
53+
// see: https://man7.org/linux/man-pages/man3/shm_open.3.html
54+
ipc::string op_name = ipc::string{"/"} + name;
5255
// Open the object for read-write access.
5356
int flag = O_RDWR;
5457
switch (mode) {
@@ -65,17 +68,17 @@ id_t acquire(char const * name, std::size_t size, unsigned mode) {
6568
flag |= O_CREAT;
6669
break;
6770
}
68-
int fd = ::shm_open(name, flag, S_IRUSR | S_IWUSR |
69-
S_IRGRP | S_IWGRP |
70-
S_IROTH | S_IWOTH);
71+
int fd = ::shm_open(op_name.c_str(), flag, S_IRUSR | S_IWUSR |
72+
S_IRGRP | S_IWGRP |
73+
S_IROTH | S_IWOTH);
7174
if (fd == -1) {
72-
ipc::error("fail shm_open[%d]: %s\n", errno, name);
75+
ipc::error("fail shm_open[%d]: %s\n", errno, op_name.c_str());
7376
return nullptr;
7477
}
7578
auto ii = mem::alloc<id_info_t>();
7679
ii->fd_ = fd;
7780
ii->size_ = size;
78-
ii->name_ = name;
81+
ii->name_ = std::move(op_name);
7982
return ii;
8083
}
8184

@@ -158,7 +161,8 @@ std::int32_t release(id_t id) {
158161
std::int32_t ret = -1;
159162
auto ii = static_cast<id_info_t*>(id);
160163
if (ii->mem_ == nullptr || ii->size_ == 0) {
161-
ipc::error("fail release: invalid id (mem = %p, size = %zd)\n", ii->mem_, ii->size_);
164+
ipc::error("fail release: invalid id (mem = %p, size = %zd), name = %s\n",
165+
ii->mem_, ii->size_, ii->name_.c_str());
162166
}
163167
else if ((ret = acc_of(ii->mem_, ii->size_).fetch_sub(1, std::memory_order_acq_rel)) <= 1) {
164168
::munmap(ii->mem_, ii->size_);

‎test/test_ipc.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,15 @@ void test_sr(char const * name, int s_cnt, int r_cnt) {
151151

152152
} // internal-linkage
153153

154-
TEST(IPC, basic) {
154+
TEST(IPC, basic_ssu) {
155155
test_basic<relat::single, relat::single, trans::unicast >("ssu");
156-
//test_basic<relat::single, relat::multi , trans::unicast >("smu");
157-
//test_basic<relat::multi , relat::multi , trans::unicast >("mmu");
156+
}
157+
158+
TEST(IPC, basic_smb) {
158159
test_basic<relat::single, relat::multi , trans::broadcast>("smb");
160+
}
161+
162+
TEST(IPC, basic_mmb) {
159163
test_basic<relat::multi , relat::multi , trans::broadcast>("mmb");
160164
}
161165

‎test/test_sync.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ TEST(Sync, Condition) {
131131
{
132132
std::lock_guard<ipc::sync::mutex> guard {lock};
133133
while (que.empty()) {
134-
EXPECT_TRUE(cond.wait(lock, 1000));
134+
ASSERT_TRUE(cond.wait(lock, 1000));
135135
}
136136
val = que.front();
137137
que.pop_front();

0 commit comments

Comments
 (0)
Please sign in to comment.