Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-13505

QPluginLoader unload() deletes root component even if plugin not really unloaded

    XMLWordPrintable

Details

    • Bug
    • Resolution: Incomplete
    • P2: Important
    • 4.8.x
    • 4.5.2
    • Core: Plugins
    • None
    • Windows XP 64bit, Visual Studio 2005

    Description

      Hi.

      I don't know if this is really a bug or a misinterpretation of the documentation but I have the following problem:

      	QString filename = "myplugin.dll";
      	QPointer<QObject> plugin1 = NULL;
      	QPointer<QObject> plugin2 = NULL;
      
      	// uncomment the brackets to show the problem
      	//{
      	QPluginLoader loader1(filename);
      	plugin1 = loader1.instance();
      	//}
      
      	QPluginLoader loader2(filename);
      	plugin2 = loader2.instance();
      
      	Q_ASSERT(plugin1==plugin2);
      	Q_ASSERT(!plugin1.isNull());
      
      	loader2.unload();
      
      	Q_ASSERT(!plugin1.isNull());
      

      This code works as intended: loader2.unload() has no effect because loader1 is still holding the plugin alive.

      But if I uncomment the both brackets around loader1 the behaviour is changing unexpectedly. Documentation of QPluginLoader destructor says, if no unload() was done before, the plugin should stay in memory till application ends. But now at loader2.unload() the plugin instance qobject is deleted!

      Partially the documentation is right because the DLL isn't unloaded, but then I expect the plugin instance to stay alive too. If loader1 is deleted without unload() called before, the plugin DLL "lives" till application end, so should the plugin instance.

      Diving into the code, I found that if the last living QPluginLoader instance for a DLL is deleted, the internal QLibraryPrivate object is deleted too and the internal libraryUnloadCount reference counter is lost. On the other hand without brackets, where loader1 is not deleted, the unload counter stays valid.

      Maybe this is the intended behaviour and I misinterpreted the documentation, but I wanted to share my thoughts.
      In any case in the above example instance() (and implicitly load()) is called once more than unload(), so I not only expected the DLL to stay in memory but also I expected the instance to stay valid until application end.

      Concretely I load the same plugins at different places in my code to cast them to different interfaces, but these places don't know from each other. So unloading an "unneeded" plugin at one place could destroy the plugin instance qobject at the other place even if the DLL is not really unloaded, which is really a bad thing you can imagine.

      I know loading and instantiating may be different things, but then this should be pointed out in the documentation at least. If I call instance() somewhere for a QPluginLoader, a second QPluginLoader somewhere else cannot know if the shared plugin instance qobject is still in use when its unload() is called. So this may rather be a problem of the whole pluginloader logic.

      Looking forward for your comments and best regards,
      Mark

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            Unassigned Unassigned
            mhoffmann Mark Hoffmann
            Votes:
            1 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes