Как безопасно использовать глобальную переменную в общей библиотеке dlopen-ed? - PullRequest
0 голосов
/ 07 марта 2019

Один из моих проектов для Linux использует много общих библиотек, которые связаны с dlopen/dlsym/dlclose для получения модульности.По соображениям безопасности потоков мне нужно поместить глобальную переменную (boost::mutex) в одну из разделяемых библиотек.Очевидно, boost::mutex имеет нетривиальный деструктор .(это может даже abort(3) программа).

Я понимаю, что использование глобальных переменных, которые не являются тривиально разрушаемыми, является плохой идеей, и некоторые рекомендации явно запрещают делать такие вещи, но ядействительно нужен глобальный мьютекс для модуля.

После добавления глобальной переменной boost::mutex происходит сбой при выходе из программы.(boost::mutex::lock() throws из-за EINVAL из pthread_mutex_lock) Я предполагаю, что общий либриал вызван после main, но этот мьютекс уже уничтожен.(Я полагаю, что статические разрушения в порядке фиктивных вещей).

К сожалению, эта программа довольно сложна, и мне нужен обходной путь, чтобы выполнять свою работу вовремя.Покопав вещи ctor / dtor, я обнаружил, что этот код работает.

#include <boost/aligned_storage.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/type_traits/alignment_of.hpp>

boost::aligned_storage<sizeof(boost::mutex), boost::alignment_of<boost::mutex>::value> gMutexStorage;
boost::mutex* gMutex = NULL;

__attribute__ ((constructor))
void MyModuleInit()
{
    gMutex = new(reinterpret_cast<boost::mutex*>(gMutexStorage.address())) boost::mutex();
}

__attribute__ ((destructor))
void MyModuleUnInit()
{
    gMutex->~mutex();
    gMutex = NULL;
}

// global mutex use
extern "C" __attribute__ ((visibility("default")))
int SomeFunc(...)
{
    boost::lock_guard<boost::mutex> guard(*gMutex);
    ....
}

Затем эта MyModuleUnInit функция зарегистрирована в секции .fini_array (Для справки, другой деструктор статической переменной C ++, зарегистрированной в __cxa_atexit) разделяемой библиотеки, и она вызывается после использования мьютекса, поэтому программа завершается нормально.

Однако я не уверен в безопасности использования этого мьютекса.Можно ли использовать этот код?Если нет, как я могу справиться со статической (глобальной) переменной для общей библиотеки dlopen-ed?

...