dlclose() entlädt die Bibliothek nicht - was können die Gründe sein?
-
Hallo Zusammen!
Wir portieren gerade eine Windows-Applikation auf Linux und mussten feststellen, dass das Linux Shared Object Konzept sich doch in manchen Grundsätzen vom Windows DLL Konzept unterscheidet.
Und zwar habe wir gerade das Problem, dass
dlclose()
eine mitdlopen()
geladene Bibliothek nicht entlädt (das checken wir mitcat /proc/ID/maps
) und auch keinen Fehlercode zurückgibt. Unter Windows funktioniert das Entladen einwandfrei - es muss also etwas damit zu tun haben, dass unter Linux an das Entladen andere Bedingungen gestellt werden. Und in der tat steht in der Doku:If the reference count drops to zero and no other loaded libraries use symbols in it, then the dynamic library is unloaded.
Die zweite Bedingung ist mir nicht ganz klar. Was bedeutet es, dass andere Bibliotheken "Symbole benutzen"? Wenn eine Bibliothek explizit gelinkt wird (sprich per
dlopen()
), dann besteht meinem Verständis (d.h. dem Windows-Verständis ) nach die einzige Möglichkeit "Symoble zu benutzen" darin, diese mitdlsym()
anzufordern. Es gibt jedoch keine Möglichkeit diese wieder freizugeben.Kann mir jemand in diesem Zusammenhang helfen zu verstehen, was es unter Linux bedeutet, dass "Symbole benutzt" werden (offensichtlich sind nicht die mit
dlsym()
angeforderten Symbole gemeint) und wie (in welchen Fälle, Beispiele?) kann diesdlclose()
davon abhalten eine Bibliothek zu entladen.Da ich wirklich davon ausgene, dass es sich um ein Konzept-Verständnisproblem handelt, möchte ich hier bewusst niemanden mit Codedetails belasten.
Bin für jeden Hinweis dankbar.
Vielen Dank im VorausKonstantin
-
Wird bei dlclose entsprechend aufgeraeumt, also Destruktoren globaler Objekte aufgerufen?
-
Ja, globale und auch statisch Objekte.
-
Dann wird sie entladen. Ob das Betriebssystem entscheidet, sie trotzdem noch vorzuhalten, ist doch seine Sache.
Zu deiner Frage:
Was bedeutet es, dass andere Bibliotheken "Symbole benutzen"?
Du kannst mttels Kompiler gegen die Bibliothek linken. Wenn dann mittles dlopen und dlclose die Bibliothek entladen wird, dann wird sie eben nicht entladen.
-
Ach jetzt verstehe ich wie die Frage gemeint war. Was ich meinte war, dass es globale und statische Objekte gibt, die zerstört werden sollten, aber ob es tatsächlich passiert, muss ich noch einen Kollegen fragen (er ist mit der Portierung beschäftigt). Ich würde aber davon ausgehen, dass es passiert.
Dann ist also folgendes unter Linux nicht möglich (jetzt muss ich doch mit Codedetails belasten):
handle = dlopen(filePath, RTLD_LAZY); dlclose(handle); //check that the library is really unloaded assert( dlopen(filePath_.c_str(), RTLD_NOLOAD) == 0) );
-
knivil schrieb:
Zu deiner Frage:
Was bedeutet es, dass andere Bibliotheken "Symbole benutzen"?
Du kannst mttels Kompiler gegen die Bibliothek linken. Wenn dann mittles dlopen und dlclose die Bibliothek entladen wird, dann wird sie eben nicht entladen.
Das ist das erste, was mir in den Sinn kam. Erstens wird bei uns die besagte Bibliothek nicht auch noch implizit gelinkt und zweites haben wir diesen Fall an einem einfachen Beispiel getestet und es _ist_ möglich eine implizit gelinkte Bibliothek per dlclose() zu entlanden.
-
knivil schrieb:
Wird bei dlclose entsprechend aufgeraeumt, also Destruktoren globaler Objekte aufgerufen?
Ich muss mich nun korrigieren: die Destruktoren globaler Objekte werden nicht aufgerufen. Was kann das Problem sein, eine Idee?
-
Minimalbeispiel bauen, bei dem es funktioniert. Vergleichen mit dem Problemprogramm, was anders ist.
-
Ein Kollege hat schon alle möglichen Minimalbeispiele gebaut und versucht dlcose() dazu zu bringen nicht zu funktionieren - aber es funktioniert. Es ist sehr schwer es mit dem Problemprogramm zu vergleichen - es ist sehr viel Code.
Deswegen habe ich ja gefragt, was es unter Linux bedeutet, dass "Symbole benutzt werden" und ob jemand so ein Beipspiel wo dlclose() nicht funktioniert konstruieren kann.
-
k-sok schrieb:
Ein Kollege hat schon alle möglichen Minimalbeispiele gebaut und versucht dlcose() dazu zu bringen nicht zu funktionieren - aber es funktioniert. Es ist sehr schwer es mit dem Problemprogramm zu vergleichen - es ist sehr viel Code.
Deswegen habe ich ja gefragt, was es unter Linux bedeutet, dass "Symbole benutzt werden" und ob jemand so ein Beipspiel wo dlclose() nicht funktioniert konstruieren kann.
Das Symbole benutzt werden ist einfach so zu verstehen, dass ein anderes Programm die bibliothek benutzt.
Programm A benutzt dlopen
Programm B benutzt dlopen für die selbe bibliothek.Programm A benutzt dlclose, jetzt wird die bibliothek logischerweise nicht entladen, da Programm B diese noch benutzt.
Implementiert ist das über nen internen counter, jedes dlopen erhöht ihn um eins jedes dlclose verringert ihn um eins. Ist der counter auf 0, wird die bibliothek entladen.
Braucht dich also gar nicht zu interessieren.Ich nehm mal an, dass dein Programm das einzige ist, das Bibliothek benutzt. Ich könnte mir höchstens vorstellen, dass der kernel die bibliothek im RAM behält falls zu einem späteren Zeitpunkt ein anderes Programm die noch brauchen sollte.
Kannst es ja mal unter hoher RAM-last probieren, so dass er swappen muss, dann sollte er sie entladen.Ansonsten: Prüf über nen eigenen Zähler oder gdb dass dlopen und dlclose jeweils nur einmal aufgerufen werden und der handle den du bei dlclose benutzt der Richtige ist. Wenn das alles stimmt hast du nichts falsch gemacht und der Kernel hat einfach keine Lust es zu entladen. Dagegen kannst du nichts und solltest du auch nicht, weil es keinen Nutzen hätte.
-
Hallo.
Danke für die Antworten aber wir haben schon rausgefunden, dass es eine Art Bug auf Fedora ist. Auf zwei anderen Distributionen funktioniert es wie es soll.
Hier gibts mehr Informationen dazu:
http://www.redhat.com/archives/posix-c++-wg/2009-August/msg00002.html