修正全局变量初始化时序问题导致的内存访问异常

This commit is contained in:
mutouyun 2023-02-11 18:08:55 +08:00 committed by 木头云
parent 768e58f605
commit 162011d4b4
7 changed files with 59 additions and 13 deletions

View File

@ -19,6 +19,8 @@ enum : unsigned {
template <typename Flag> template <typename Flag>
struct IPC_EXPORT chan_impl { struct IPC_EXPORT chan_impl {
static ipc::handle_t inited();
static bool connect (ipc::handle_t * ph, char const * name, unsigned mode); static bool connect (ipc::handle_t * ph, char const * name, unsigned mode);
static bool reconnect (ipc::handle_t * ph, unsigned mode); static bool reconnect (ipc::handle_t * ph, unsigned mode);
static void disconnect(ipc::handle_t h); static void disconnect(ipc::handle_t h);
@ -41,7 +43,7 @@ class chan_wrapper {
private: private:
using detail_t = chan_impl<Flag>; using detail_t = chan_impl<Flag>;
ipc::handle_t h_ = nullptr; ipc::handle_t h_ = detail_t::inited();
unsigned mode_ = ipc::sender; unsigned mode_ = ipc::sender;
bool connected_ = false; bool connected_ = false;

View File

@ -630,6 +630,12 @@ using policy_t = ipc::policy::choose<ipc::circ::elem_array, Flag>;
namespace ipc { namespace ipc {
template <typename Flag>
ipc::handle_t chan_impl<Flag>::inited() {
ipc::detail::waiter::init();
return nullptr;
}
template <typename Flag> template <typename Flag>
bool chan_impl<Flag>::connect(ipc::handle_t * ph, char const * name, unsigned mode) { bool chan_impl<Flag>::connect(ipc::handle_t * ph, char const * name, unsigned mode) {
return detail_impl<policy_t<Flag>>::connect(ph, name, mode & receiver); return detail_impl<policy_t<Flag>>::connect(ph, name, mode & receiver);

View File

@ -125,8 +125,8 @@ class mutex {
IPC_UNUSED_ std::lock_guard<std::mutex> guard {info.lock}; IPC_UNUSED_ std::lock_guard<std::mutex> guard {info.lock};
auto it = info.mutex_handles.find(name); auto it = info.mutex_handles.find(name);
if (it == info.mutex_handles.end()) { if (it == info.mutex_handles.end()) {
it = curr_prog::get().mutex_handles.emplace(name, it = info.mutex_handles.emplace(name,
curr_prog::shm_data::init{name}).first; curr_prog::shm_data::init{name}).first;
} }
mutex_ = &it->second.mtx; mutex_ = &it->second.mtx;
ref_ = &it->second.ref; ref_ = &it->second.ref;
@ -135,13 +135,14 @@ class mutex {
template <typename F> template <typename F>
void release_mutex(ipc::string const &name, F &&clear) { void release_mutex(ipc::string const &name, F &&clear) {
if (name.empty()) return; if (name.empty()) return;
IPC_UNUSED_ std::lock_guard<std::mutex> guard {curr_prog::get().lock}; auto &info = curr_prog::get();
auto it = curr_prog::get().mutex_handles.find(name); IPC_UNUSED_ std::lock_guard<std::mutex> guard {info.lock};
if (it == curr_prog::get().mutex_handles.end()) { auto it = info.mutex_handles.find(name);
if (it == info.mutex_handles.end()) {
return; return;
} }
if (clear()) { if (clear()) {
curr_prog::get().mutex_handles.erase(it); info.mutex_handles.erase(it);
} }
} }
@ -149,6 +150,11 @@ public:
mutex() = default; mutex() = default;
~mutex() = default; ~mutex() = default;
static void init() {
// Avoid exception problems caused by static member initialization order.
curr_prog::get();
}
a0_mtx_t const *native() const noexcept { a0_mtx_t const *native() const noexcept {
return valid() ? mutex_->native() : nullptr; return valid() ? mutex_->native() : nullptr;
} }

View File

@ -55,8 +55,8 @@ class mutex {
IPC_UNUSED_ std::lock_guard<std::mutex> guard {info.lock}; IPC_UNUSED_ std::lock_guard<std::mutex> guard {info.lock};
auto it = info.mutex_handles.find(name); auto it = info.mutex_handles.find(name);
if (it == info.mutex_handles.end()) { if (it == info.mutex_handles.end()) {
it = curr_prog::get().mutex_handles.emplace(name, it = info.mutex_handles.emplace(name,
curr_prog::shm_data::init{name, sizeof(pthread_mutex_t)}).first; curr_prog::shm_data::init{name, sizeof(pthread_mutex_t)}).first;
} }
shm_ = &it->second.shm; shm_ = &it->second.shm;
ref_ = &it->second.ref; ref_ = &it->second.ref;
@ -69,13 +69,14 @@ class mutex {
template <typename F> template <typename F>
void release_mutex(ipc::string const &name, F &&clear) { void release_mutex(ipc::string const &name, F &&clear) {
if (name.empty()) return; if (name.empty()) return;
IPC_UNUSED_ std::lock_guard<std::mutex> guard {curr_prog::get().lock}; auto &info = curr_prog::get();
auto it = curr_prog::get().mutex_handles.find(name); IPC_UNUSED_ std::lock_guard<std::mutex> guard {info.lock};
if (it == curr_prog::get().mutex_handles.end()) { auto it = info.mutex_handles.find(name);
if (it == info.mutex_handles.end()) {
return; return;
} }
if (clear()) { if (clear()) {
curr_prog::get().mutex_handles.erase(it); info.mutex_handles.erase(it);
} }
} }
@ -83,6 +84,11 @@ public:
mutex() = default; mutex() = default;
~mutex() = default; ~mutex() = default;
static void init() {
// Avoid exception problems caused by static member initialization order.
curr_prog::get();
}
pthread_mutex_t const *native() const noexcept { pthread_mutex_t const *native() const noexcept {
return mutex_; return mutex_;
} }

View File

@ -21,6 +21,8 @@ public:
mutex() noexcept = default; mutex() noexcept = default;
~mutex() noexcept = default; ~mutex() noexcept = default;
static void init() {}
HANDLE native() const noexcept { HANDLE native() const noexcept {
return h_; return h_;
} }

View File

@ -0,0 +1,22 @@
#include "libipc/waiter.h"
#include "libipc/platform/detail.h"
#if defined(IPC_OS_WINDOWS_)
#include "libipc/platform/win/mutex.h"
#elif defined(IPC_OS_LINUX_)
#include "libipc/platform/linux/mutex.h"
#elif defined(IPC_OS_QNX_)
#include "libipc/platform/posix/mutex.h"
#else/*IPC_OS*/
# error "Unsupported platform."
#endif
namespace ipc {
namespace detail {
void waiter::init() {
ipc::detail::sync::mutex::init();
}
} // namespace detail
} // namespace ipc

View File

@ -19,6 +19,8 @@ class waiter {
std::atomic<bool> quit_ {false}; std::atomic<bool> quit_ {false};
public: public:
static void init();
waiter() = default; waiter() = default;
waiter(char const *name) { waiter(char const *name) {
open(name); open(name);