Skip to content

Commit 162011d

Browse files
committed
修正全局变量初始化时序问题导致的内存访问异常
1 parent 768e58f commit 162011d

File tree

7 files changed

+59
-13
lines changed

7 files changed

+59
-13
lines changed

include/libipc/ipc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ enum : unsigned {
1919

2020
template <typename Flag>
2121
struct IPC_EXPORT chan_impl {
22+
static ipc::handle_t inited();
23+
2224
static bool connect (ipc::handle_t * ph, char const * name, unsigned mode);
2325
static bool reconnect (ipc::handle_t * ph, unsigned mode);
2426
static void disconnect(ipc::handle_t h);
@@ -41,7 +43,7 @@ class chan_wrapper {
4143
private:
4244
using detail_t = chan_impl<Flag>;
4345

44-
ipc::handle_t h_ = nullptr;
46+
ipc::handle_t h_ = detail_t::inited();
4547
unsigned mode_ = ipc::sender;
4648
bool connected_ = false;
4749

src/libipc/ipc.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,12 @@ using policy_t = ipc::policy::choose<ipc::circ::elem_array, Flag>;
630630

631631
namespace ipc {
632632

633+
template <typename Flag>
634+
ipc::handle_t chan_impl<Flag>::inited() {
635+
ipc::detail::waiter::init();
636+
return nullptr;
637+
}
638+
633639
template <typename Flag>
634640
bool chan_impl<Flag>::connect(ipc::handle_t * ph, char const * name, unsigned mode) {
635641
return detail_impl<policy_t<Flag>>::connect(ph, name, mode & receiver);

src/libipc/platform/linux/mutex.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ class mutex {
125125
IPC_UNUSED_ std::lock_guard<std::mutex> guard {info.lock};
126126
auto it = info.mutex_handles.find(name);
127127
if (it == info.mutex_handles.end()) {
128-
it = curr_prog::get().mutex_handles.emplace(name,
129-
curr_prog::shm_data::init{name}).first;
128+
it = info.mutex_handles.emplace(name,
129+
curr_prog::shm_data::init{name}).first;
130130
}
131131
mutex_ = &it->second.mtx;
132132
ref_ = &it->second.ref;
@@ -135,20 +135,26 @@ class mutex {
135135
template <typename F>
136136
void release_mutex(ipc::string const &name, F &&clear) {
137137
if (name.empty()) return;
138-
IPC_UNUSED_ std::lock_guard<std::mutex> guard {curr_prog::get().lock};
139-
auto it = curr_prog::get().mutex_handles.find(name);
140-
if (it == curr_prog::get().mutex_handles.end()) {
138+
auto &info = curr_prog::get();
139+
IPC_UNUSED_ std::lock_guard<std::mutex> guard {info.lock};
140+
auto it = info.mutex_handles.find(name);
141+
if (it == info.mutex_handles.end()) {
141142
return;
142143
}
143144
if (clear()) {
144-
curr_prog::get().mutex_handles.erase(it);
145+
info.mutex_handles.erase(it);
145146
}
146147
}
147148

148149
public:
149150
mutex() = default;
150151
~mutex() = default;
151152

153+
static void init() {
154+
// Avoid exception problems caused by static member initialization order.
155+
curr_prog::get();
156+
}
157+
152158
a0_mtx_t const *native() const noexcept {
153159
return valid() ? mutex_->native() : nullptr;
154160
}

src/libipc/platform/posix/mutex.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ class mutex {
5555
IPC_UNUSED_ std::lock_guard<std::mutex> guard {info.lock};
5656
auto it = info.mutex_handles.find(name);
5757
if (it == info.mutex_handles.end()) {
58-
it = curr_prog::get().mutex_handles.emplace(name,
59-
curr_prog::shm_data::init{name, sizeof(pthread_mutex_t)}).first;
58+
it = info.mutex_handles.emplace(name,
59+
curr_prog::shm_data::init{name, sizeof(pthread_mutex_t)}).first;
6060
}
6161
shm_ = &it->second.shm;
6262
ref_ = &it->second.ref;
@@ -69,20 +69,26 @@ class mutex {
6969
template <typename F>
7070
void release_mutex(ipc::string const &name, F &&clear) {
7171
if (name.empty()) return;
72-
IPC_UNUSED_ std::lock_guard<std::mutex> guard {curr_prog::get().lock};
73-
auto it = curr_prog::get().mutex_handles.find(name);
74-
if (it == curr_prog::get().mutex_handles.end()) {
72+
auto &info = curr_prog::get();
73+
IPC_UNUSED_ std::lock_guard<std::mutex> guard {info.lock};
74+
auto it = info.mutex_handles.find(name);
75+
if (it == info.mutex_handles.end()) {
7576
return;
7677
}
7778
if (clear()) {
78-
curr_prog::get().mutex_handles.erase(it);
79+
info.mutex_handles.erase(it);
7980
}
8081
}
8182

8283
public:
8384
mutex() = default;
8485
~mutex() = default;
8586

87+
static void init() {
88+
// Avoid exception problems caused by static member initialization order.
89+
curr_prog::get();
90+
}
91+
8692
pthread_mutex_t const *native() const noexcept {
8793
return mutex_;
8894
}

src/libipc/platform/win/mutex.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ class mutex {
2121
mutex() noexcept = default;
2222
~mutex() noexcept = default;
2323

24+
static void init() {}
25+
2426
HANDLE native() const noexcept {
2527
return h_;
2628
}

src/libipc/sync/waiter.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include "libipc/waiter.h"
2+
3+
#include "libipc/platform/detail.h"
4+
#if defined(IPC_OS_WINDOWS_)
5+
#include "libipc/platform/win/mutex.h"
6+
#elif defined(IPC_OS_LINUX_)
7+
#include "libipc/platform/linux/mutex.h"
8+
#elif defined(IPC_OS_QNX_)
9+
#include "libipc/platform/posix/mutex.h"
10+
#else/*IPC_OS*/
11+
# error "Unsupported platform."
12+
#endif
13+
14+
namespace ipc {
15+
namespace detail {
16+
17+
void waiter::init() {
18+
ipc::detail::sync::mutex::init();
19+
}
20+
21+
} // namespace detail
22+
} // namespace ipc

src/libipc/waiter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class waiter {
1919
std::atomic<bool> quit_ {false};
2020

2121
public:
22+
static void init();
23+
2224
waiter() = default;
2325
waiter(char const *name) {
2426
open(name);

0 commit comments

Comments
 (0)