Visual Plugin causing AV

I have a Delphi host with Delphi plugins, both visual and non-visual. This application is still in development, but has been going fine until this week–and I’m not quite sure what changed.

The visual plugins are configuration screens that get parented to pages of a TPageControl. The non-visual plugins are processes that I can launch manually. If I just open and close the application without doing anything, the plugins load and unload just fine. If I open the application and go into the configuration so that one of the pages shows (it doesn’t matter which), then I get an access violation when the application closes (not when I’m in the configuration screen or exiting it).

Just before the AV notice, I get a message that says one of my non-visual plugins cannot be unloaded because it has a reference count of 2 and one of my visual plugins has a reference count of 1.

I’m totally baffled and have looked at the code every which way I can think of and have put lots of debug messages trying to track down what is happening. Even weirder, if I take out two of the plugin modules, everything works fine, but there’s nothing strange or terribly different about the ones that are causing the problem. I even wrote another very simple visual plugin with nothing extra and it blows up too!

I keep looking at the reference count message and wondering how come the reference count is not zero. When the plugin modules are loaded and config plugins are found, they are immediately attached to the TPageControl with ShowParented. But it’s like they don’t get called (or instantiated) until the TPageControl actually becomes visible when I call up the configuration screen.

There’s one other thing I should mention about the visual “config” plugins: They have a Load method that gets called when the config shows and Save if the configuration is saved.

So I guess the first questions I have, then, revolve around the reference count. If I create the plugin with HYModuleManager and save a copy of the pointer in a TList (so I can call the Load method) and also attach it to a TPageControl, are there two references or just one with my own local pointer to it in addition to the HYModuleManager’s internal list? Why would simply viewing the TPageControl or calling the Load method seem to increase the reference count?

Thanks,
David.

Pls review Advanced Demo sample.
it uses the similar behavior, but shows plugins in treeview as nodes

I think it’s a deeper issue than this. I went to a previous version of my code that doesn’t have the reference count problem (and used to work) and tried it on two different machines (one with Windows 8 and the other with Windows 10), both in Delphi 10 Seattle, but only one upgraded to the latest update. I’ve traced it down to the Load method in the config settings. I use attributes on the class to automatically set NAME=VALUE pairs in the config file (.ini format) and the class name as the [Section]. If I comment out where it gets the section name, I no longer get the AV when closing the application.

The weirdest part is that it works for one class in one plugin but not another. I’ve stripped all the fields out of the problematic one down to one simple string field and still get the AV. I tried this from a DUnitX test and it works fine.

Perhaps something about Hydra and the use of RTTI or maybe there’s an obtuse compiler directive that got changed that I don’t realize (I’ve checked once already).

I don’t know…

OK, one big difference between the demo and what I’m trying to do is in the demo, the visual plugin’s window is not shown until it’s ready to use. What I’ve been trying to do is assign several visual plugins to different pages (sheets) of a TPageControl and then the user can just go through the ones they need. It calls “Load” for each and if the user saves the settings, the app then calls “Save” for each plugin. But they’re always parented to the TTabSheets of the TPageControl. I was using ShowParented with each new page, but the demo only calls ShowParented when the user is ready to see that particular page.

Is my approach not going to work?

can you create a simple testcase that reproduces this problem, pls?
you can attach it here or send directly to support@

That’s a good idea. Of course, my simple example works flawlessly, so there’s obviously something with my application. It might actually be in how I’m using RTTI when setting up the configuration classes, although everything I’ve read seems to indicate this shouldn’t be a problem area.

If you’re curious about what I’ve been talking about, I’ve attached a .zip MultiVisualPluginTest.zip (38.6 KB) of the source which contains a VCL host and two VCL plugin modules, one with one visual plugin and the other with two visual plugins. Each plugin is a simple configuration screen and each one gets “ShowParented” onto a new TabSheet of a PageControl and loads/saves various settings to a local .INI file. I wrote it in XE7 but should be able to be compiled in any of the “XE” versions of Delphi. I compiled it in Delphi 10 Seattle, where my crippled application is written, and it runs flawlessly there as well.

Thanks,

David.

I finally, FINALLY got to the bottom of this. It wasn’t caused by RTTI in a plugin, or a visual plugin attached to a PageControl, but a non-visual control I was simply checking when when shutting everything down. I keep references to the plugins in a list and the OnDestroy event of the main form goes through the list and frees memory before unloading. One thing I did (as a just-in-case measure) was to stop any non-visual plugin. So my clean-up looked like this:

for i := FPluginList.Count -1 downto 0 do begin (FPluginList.Items[i] as IHYNonVisualPlugin).Stop; FPluginList.Items[i] := nil; FPluginList.Delete(i); end;

I found that calling “Stop” was somehow adding a reference to the plugin so that when the modules were unloaded, the ModuleManager was giving me an error. The weird thing was that it didn’t always happen. The most consistent thing I saw was when I would view any one of the visual plugins it would cause the error, so that’s where I was looking at first. I still don’t know why that triggered a different plugin to get referenced, but now all I do in the OnDestroy is call FPluginList.Free; and everything is fine.

I think there are some things concerning interfaces and references I don’t completely understand!

David.