You are not logged in.

#1 2011-02-14 09:51:17

BenderRodriguez
Member
Registered: 2010-07-05
Posts: 16
Website

Unable to dlclose() shared object when compiled with gcc-4.5

Hi,

my application implements an interface to load shared objects. While playing around with boost in a shared object I've noticed that dlclose() does not unload the shared object anymore. I've checked the linker output (LD_DEBUG etc.) but nothing provided some clues. Searching the internet provided something interesting: http://www.cygwin.com/ml/libc-help/2010 … 00013.html
The thread describes the very same problem and gives an example.

// g++ -shared -fPIC -O0 -o libtest.so libtest.cpp

template<class T>
void test()
{
  static const int N[1] = {0};
  int i=N[0];
}

void blubbels()
{
  test<short>();
}

// g++ -ldl -o test_dlopen test_dlopen.cpp && ./test_dlopen /path/to/libtest.so

#include <dlfcn.h>
#include <iostream>
#include <link.h>

int cb(struct dl_phdr_info* info, size_t size, void* data)
{
  std::cout << info->dlpi_name << std::endl;
  return 0;
}


int main(int argc, char** argv)
{
  const char* default_path = "./libtest.so";
  const char* path = default_path;
  if (argc >= 2) {
    path = argv[1];
  }

  std::cout << "Loaded libraries before dynamic loading:" << std::endl;
  dl_iterate_phdr(cb, 0);
  
  void* h = dlopen(path, RTLD_NOW);
  std::cout << "Handle: " << h << std::endl;
  std::cout << "Loaded libraries after dynamic loading:" << std::endl;
  dl_iterate_phdr(cb, 0);
  
  std::cout << "dlclose return: " << dlclose(h) << std::endl;
  std::cout << "Loaded libraries after closing handle:" << std::endl;
  dl_iterate_phdr(cb, 0);

  return 0;
}

I've tested this example and tried "solution" given in this thread. The second listing of the loaded objects should not list "libtest.so" as loaded. The problem is reproducible and recompiling (application and library) with gcc-4.4 from AUR "solves" the problem (libtest.so is removed from memory after call to dlclose()).  I'm not sure if this is related to the platform but I'm on x86_64. 

I know, basically dlclose() is not supposed to actually unload the library but to decrement the objects reference count. As you can see the example is very straight forward and AFAIK there is no obvious reason to leave the SO in memory.
Is this a bug in gcc or is this intended behavior? Neither I have found a bug report in gcc's bug tracker nor in the Arch bug  tracker.
Can anyone test the example?
Thanks for reading smile

Offline

#2 2011-02-14 10:16:17

Allan
Pacman
From: Brisbane, AU
Registered: 2007-06-09
Posts: 11,405
Website

Re: Unable to dlclose() shared object when compiled with gcc-4.5

The reply to the post you linked to clearly states that this is not a bug.

Offline

#3 2011-02-14 11:47:00

BenderRodriguez
Member
Registered: 2010-07-05
Posts: 16
Website

Re: Unable to dlclose() shared object when compiled with gcc-4.5

Allan wrote:

The reply to the post you linked to clearly states that this is not a bug.

Did you read the whole thread? If not, please read on. The thread states that this indeed seems to be a bug of gcc.
I'm fully aware of the POSIX manual and its description of dlclose() but a lot of applications do implement some kind of plugin API (gimp?, audacious,...) and hence, are in the need of this mechanism. The given example fails with gcc-4.5 and this results in _fini() (_init()) not being  called while un-/loading the library. Unfortunately these applications may rely on this but luckily most applications don't dlclose() plugins during run time.  These applications usually just scan or load these plugins at startup and never release them(until termination). This is probably the reason why this has not been observed yet.

Offline

#4 2011-02-14 13:35:20

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: Unable to dlclose() shared object when compiled with gcc-4.5

To be clear, the bug mentioned in that thread is specifically this: if you dlclose, then change the library, and dlopen again, the old version of the library is loaded, not the new version on disk.

The fact that the lib stays in memory after dlclose is not a bug - the reuse of the old lib is.

Offline

#5 2011-02-14 14:20:52

BenderRodriguez
Member
Registered: 2010-07-05
Posts: 16
Website

Re: Unable to dlclose() shared object when compiled with gcc-4.5

Cerebral wrote:

To be clear, the bug mentioned in that thread is specifically this: if you dlclose, then change the library, and dlopen again, the old version of the library is loaded, not the new version on disk.

Correct.

Cerebral wrote:

The fact that the lib stays in memory after dlclose is not a bug - the reuse of the old lib is.

So libraries are supposed to stay in memory? Just in case anyone might need them? I don't want to sound rude but if that's the case, then you might want to explain that a little more thoroughly. What's the difference between gcc-4.4 and gcc-4.5?
Can you point me to somewhere in the POSIX manual supporting your statement? I'm not aware of any caching mechanism in the dynamic loader/linker.

BTW: I'm not saying it is a bug. I was asking. The conclusion in the linked thread seemed to be that this might be a bug in gcc.
Even more BTW: The whole system (which is quite a few lines of code) are working on a linux cluster (gcc-4.4) without any problems.  We are running this configuration for almost 2 years now and the problems occurs on my development system.

Offline

#6 2011-02-14 21:43:02

Allan
Pacman
From: Brisbane, AU
Registered: 2007-06-09
Posts: 11,405
Website

Re: Unable to dlclose() shared object when compiled with gcc-4.5

The example you give in this thread is not a bug.   The first reply to the link you gave quotes the relevant section of POSIX.

The example given much later in that thread is a bug.  But it is doing something different to your test case above.  The failure there is the second dlopen().

However, it is likely that your "not bug" and the actual bug are related.  It appears no-one ever filed a bug report anywhere for the actual bug...  but given we know the failure occurs between gcc-4.4 and gcc-4.5, it should be easy to do a git bisect and find the commit causing this.

Offline

Board footer

Powered by FluxBB