Work around an unfixed glibc bug in dlclose(3) on exit

During exit, libraries are unloaded and global destructors are run. If
we call dlclose(3) from inside the global destructors, we might be
telling libdl to unload a module it has already unloaded.

I cannot reproduce the issue on my Fedora 17 machine with glibc 2.15,
but it could be reliably be reproduced on an Ubuntu 11.10. The assertion
is identical to the one reported upstream at
http://sourceware.org/bugzilla/show_bug.cgi?id=11941 (see better
explanation at https://bugzilla.novell.com/show_bug.cgi?id=622977). I
cannot find any evidence in glibc's source code that the bug has been
fixed.

Change-Id: I97745f89e8c5481196e645dada8762d607a9fb2c
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Thiago Macieira 2013-01-27 22:38:32 -08:00 committed by The Qt Project
parent 288d3aceee
commit 0da5471664
2 changed files with 14 additions and 4 deletions

View File

@ -376,7 +376,14 @@ inline void QLibraryStore::cleanup()
Q_ASSERT(lib->pHnd);
Q_ASSERT(lib->libraryUnloadCount.load() > 0);
lib->libraryUnloadCount.store(1);
#ifdef __GLIBC__
// glibc has a bug in unloading from global destructors
// see https://bugzilla.novell.com/show_bug.cgi?id=622977
// and http://sourceware.org/bugzilla/show_bug.cgi?id=11941
lib->unload(QLibraryPrivate::NoUnloadSys);
#else
lib->unload();
#endif
delete lib;
it.value() = 0;
}
@ -490,15 +497,16 @@ bool QLibraryPrivate::load()
return ret;
}
bool QLibraryPrivate::unload()
bool QLibraryPrivate::unload(UnloadFlag flag)
{
if (!pHnd)
return false;
if (!libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
delete inst.data();
if (unload_sys()) {
if (flag == NoUnloadSys || unload_sys()) {
if (qt_debug_component())
qWarning() << "QLibraryPrivate::unload succeeded on" << fileName;
qWarning() << "QLibraryPrivate::unload succeeded on" << fileName
<< (flag == NoUnloadSys ? "(faked)" : "");
//when the library is unloaded, we release the reference on it so that 'this'
//can get deleted
libraryRefCount.deref();

View File

@ -83,12 +83,14 @@ public:
#endif
pHnd;
enum UnloadFlag { UnloadSys, NoUnloadSys };
QString fileName, qualifiedFileName;
QString fullVersion;
bool load();
bool loadPlugin(); // loads and resolves instance
bool unload();
bool unload(UnloadFlag flag = UnloadSys);
void release();
QFunctionPointer resolve(const char *);