dlclose не вызывает деструкторы библиотеки, dlopen называется только один раз

рассмотрим следующий код для динамически загружаемой библиотеки, построенной с g ++ - 4.7 на linux, -fPIC и связанной с опцией -rdynamic:

typedef std::vector< void* > cbRegister_t;

struct Wrapper
{
    cbRegister_t instance;
    Wrapper() : instance() { HDebugLog("Wrapper CTOR!");}
    ~Wrapper() { HDebugLog("Wrapper DESTRUCTOR!"); }
};
inline cbRegister_t& getLibraryUnregisterMap()
{
    static Wrapper unregisterLibraryMap;
    HDebugLog("getLibraryUnregisterMap: we have " <<unregisterLibraryMap.instance.size() << " elements. the address of the map is " << &unregisterLibraryMap.instance);
    return unregisterLibraryMap.instance;
}

void registerLibrary(void* p)
{
  auto& map = getLibraryUnregisterMap();
  map.push_back(p);
}

void unregisterLibrary()
{
  auto& map = getLibraryUnregisterMap();
}

void __attribute__ ((constructor)) library_init()
{
  static SomeData cbContainer;
  HDebugLog("Library constructor: address of static cbContainer is: " << &cbContainer );
  registerLibrary( &cbContainer);
} 
void __attribute__ ((destructor)) library_fini()
{ unregisterLibrary(); }

Этот код загружается штрафом от клиента с [ f5] и флаг RTLD_NOW. Вызывается конструктор библиотеки. Проблема возникает, когда я нахожу dlclose на дескрипторе. Он дает статус нуль, что означает, что он был успешным. Но деструктор библиотеки library_fini не вызывается. dlopen вызывается в одном месте, поэтому счетчик ссылок не должен быть проблемой, но для того, чтобы быть абсолютно уверенным, что на самом деле нет references dangling, я несколько раз пытался выполнить dlclose:

int result = dlclose(handle);
HDebugLog("Library::dynamicLibraryClose: closing library: " << libraryPath);
HDebugLog("Library::dynamicLibraryClose: dlclose 1 failed with error: " << result << " => " );
result = dlclose(handle);
HDebugLog("Library::dynamicLibraryClose: dlclose 2 failed with error: " << result << " => " );
result = dlclose(handle);
HDebugLog("Library::dynamicLibraryClose: dlclose 3 failed with error: " << result << " => " );
result = dlclose(handle);
HDebugLog("Library::dynamicLibraryClose: dlclose 4 failed with error: " << result << " => " );
result = dlclose(handle);
HDebugLog("Library::dynamicLibraryClose: dlclose 5 failed with error: " << result << " => " );
result = dlclose(handle);
HDebugLog("Library::dynamicLibraryClose: dlclose 6 failed with error: " << result << " => ");
result = dlclose(handle);
HDebugLog("Library::dynamicLibraryClose: dlclose 7 failed with error: " << result << " => ");
result = dlclose(handle);
HDebugLog("Library::dynamicLibraryClose: dlclose 8 failed with error: " << result << " => " );
HAssertMsg( !libraryPath.empty(), "library path is not set");
HAssertMsg( 0 == dlopen(libraryPath.c_str(), RTLD_NOLOAD) , "library is still loaded");
]

Все эти журналы отладки показывают, что каждый раз, когда я вызываю dlclose, результат состояния равен нулю. Успех!

Последнее утверждение, которое не подводит, подтверждает, что библиотека больше не резидент. Но на данный момент library_fini еще не вызывается!

Это поведение, безусловно, является ошибкой либо в gcc, либо в ld.so (или что-то, что использует linux / ubuntu для динамической загрузки библиотек в эти дни). Такое поведение явно не соответствует стандарту, поскольку библиотечные деструкторы должны быть запущены, если счетчик ссылок равен нулю до возвращения dlclose. библиотечные деструкторы запускаются после уничтожения Wrapper.instance, что делает деструктор библиотеки совершенно бесполезным, поскольку не может выполнить финализацию данных

1
задан 3 April 2013 в 07:39

0 ответов

Другие вопросы по тегам:

Похожие вопросы: