Один из моих проектов для 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?