Overview
Features
Download
Documentation
Community
Add-Ons & Services

Understanding the classloader

Please post support and help requests here.

Re: Understanding the classloader

Postby StrangeMan » 29 Aug 2012, 10:27

Hi there again!

Is there any option to find out, what causes the "unloadLibrary()" call to crash? so Far, thats what my code looks like now:
Code: Select all
try
   {
      PluginLoader loader;
      std::string libName("GameOfLife");
      libName += Poco::SharedLibrary::suffix(); // append .dll or .so
      loader.loadLibrary(libName);
      { // this is to be sure, the iterators are out of scope, when the lib gets unloaded
         PluginLoader::Iterator it(loader.begin());
         PluginLoader::Iterator end(loader.end());
         for (; it != end; ++it)
         {
            PluginManifest::Iterator itMan(it->second->begin());
            PluginManifest::Iterator endMan(it->second->end());
            for (; itMan != endMan; ++itMan)
               Log::logLine("AppManager","Found " + String(itMan->name()));;
         }
      }
      { // same as above...
         App* pPluginA = loader.create("AppGameOfLife");
         Log::logLine("AppManager","Name=" + pPluginA->getName());
         loader.destroy("AppGameOfLife", pPluginA);
         pPluginA = nullptr;
         Log::logLine("AppManager","Deleted");
      }
      loader.unloadLibrary(libName);
      Log::logLine("AppManager","Lib unloaded");
   }
   catch (exception &e)
   {
      Log::logLine("AppManager","Exception occured while loading plugin libraries: " + String(e.what()));
   }
   catch (...)
   {
      Log::logLine("AppManager","General Exception occured while loading plugin libraries.");
   }


It loads the library and logs the name of the class found inside. It creates an object of that class and calls a function of it. It even destroys the object. Then, at the "unalodLibrary" it crashes. No exception, no error message.

What am I missing?!

Thanks in advance,
StrangeMan
StrangeMan
 
Posts: 10
Joined: 22 Jul 2012, 12:40

Re: Understanding the classloader

Postby StrangeMan » 30 Aug 2012, 10:50

I found out, where exactly the call crashes: This is code from ClassLoader.h:
Code: Select all
void unloadLibrary(const std::string& path)
      /// Unloads the given library.
      /// Be extremely cautious when unloading shared libraries.
      /// If objects from the library are still referenced somewhere,
      /// a total crash is very likely.
      /// If the library exports a function named "pocoUninitializeLibrary",
      /// this function is executed before it is unloaded.
      /// If loadLibrary() has been called multiple times for the same
      /// library, the number of calls to unloadLibrary() must be the same
      /// for the library to become unloaded.
   {
      FastMutex::ScopedLock lock(_mutex);

      typename LibraryMap::iterator it = _map.find(path);
      if (it != _map.end())
      {
         if (--it->second.refCount == 0)
         {
            if (it->second.pLibrary->hasSymbol("pocoUninitializeLibrary"))
            {
               UninitializeLibraryFunc uninitializeLibrary = (UninitializeLibraryFunc) it->second.pLibrary->getSymbol("pocoUninitializeLibrary");
               uninitializeLibrary();
            }

            delete it->second.pManifest; // <========== It crashes on this line!
            it->second.pLibrary->unload();
            delete it->second.pLibrary;
            _map.erase(it);
         }
      }

Any idea why?

Thanks in advance,
StrangeMan
StrangeMan
 
Posts: 10
Joined: 22 Jul 2012, 12:40

Re: Understanding the classloader

Postby StrangeMan » 31 Aug 2012, 09:38

Though no ones answering, I think it's good to write my progress down here, so at least others who might stumble upon a similar situation can find a bit of help from this topic.

So in the meantime I studied the code from ClassLoader.h and tried to find out, why and when a "delete" operation could cause a crash. IMHO there are generally two cases: 1. The object/whatever that delete is trying to destroy does not exist (invalid pointer/null pointer). 2. The object/whatever was allocated on a different heap and (more importantly) by a different heap allocator.
I checked the code in ClassLoader.h and it seems the Manifest (which is, what can't be deleted) is created by the main application and is then passed to the library to fill it with its actual data. I checked my Manifest macros in the library and they seem to be fine (just three lines, like those in the pdf-example for the class loader). So reason no. 2 is not the case.
I added an if-statement to check, whether the manifest pointer is a nullptr, but thats also not the case. So IMHO the only reason left is that the manifest has been destroyed somewhere else before. And here is where I'm stuck so far.
StrangeMan
 
Posts: 10
Joined: 22 Jul 2012, 12:40

Re: Understanding the classloader

Postby StrangeMan » 31 Aug 2012, 18:12

Well, it looks like a heap problem now. I created a new project that compiles to a simple executable, so I can attach a debugger to it. I does exactly what I posted above and crashes at the same line.
Now, at the line with "delete ..." I showed two posts ago, it stops and shows this: HEAP[PluginTest.exe]: Invalid address specified to RtlValidateHeap( 001B0000, 035B6570 )

I installed Windows debugging tools and enabled different options related to the heap, e.g. heap tagging andenable page heap. Honestly, I have no idea what these actually do but different posts in different forums point into that direction. Right now, my head is smoking...

Can someone give me a hint?
StrangeMan

------------------------------------------Edit---------------------------------------------------------------

Nice, I found out, how to display a stack trace. Now I see, that the actual problem is appearing when deleting a string. Why is there a string being deleted, when the manifest is deleted? Well, when the manifest is filled with information (done by the dll) it will create an entry for each class. Part of this entry is the name of the class, stored as a string. This is done in the following macro:
Code: Select all
#define POCO_EXPORT_CLASS(cls) \
    pManifest->insert(new Poco::MetaObject<cls, _Base>(#cls));
And this string can't be deleted by the main application because it "works" with a different heap allocator.

So here, we have the problem! Unfortunately I have no idea how to fix this without editing code from the Poco code base.

See the attached image.
Attachments
Calls.png
Calls.png (69.66 KiB) Viewed 564 times
StrangeMan
 
Posts: 10
Joined: 22 Jul 2012, 12:40

Previous

Return to Support

Who is online

Users browsing this forum: No registered users and 1 guest