Freitag, 6. Juli 2018

IIS an Plugin-loading

The Loadlibrary Problem!


Since many many years I do all my Web stuff with ISAPI.DLL's on one of my Windows Server. Starting with the support of ASP.NET in Delphi I use only ASPX and background code for the webdesign. (Only one project I've done with VCL for the Web.)

The benefit with ASP.NET was, that you do not have to restart the IIS to change the code behind.

There was an ISAPI Loader from egg-Soft that was able to update the working DLL on the fly, if you upload your dll as name.upd - works great for many years.

After updating the server to 2008 R2 this loader did not work anymore… So every time I had a new version of my DLL's I had to stop and restart the IIS. Normally a 1 second interruption, if your IIS is only handling local stuff or just producing websites.

But since 5 years I have a webservice for my customer running, that depends on an external service. The service sometimes takes some time and I have many request. So stopping and restarting the IIS take 5-25 seconds and that is bad for my customer. Every development took place only at night.

Inspired by the EMBT Rad-Server project I want to build my own Service (perhaps as part of my FDK)

Project/New/ISAP.DLL but this time with loadable and unloadable plugins. My idea was - I provide you with the hard stuff and you only have to write you business code.

The FRS - Firemonkey REST - Server was born.

 
Or Fast-Remote-Service? Because in some parts the Firemonkey part in FDK is wrong, because you could use it in VCL, too - I do not have finally considered the Name. 

A working demo was done in one day (2016) - LOCAL - but my first try on a real server - nothing. No plugin could be loaded, only the root admin things are running. No idea where to look. But as always: While starting a new project - there was no time for digging into this problem.
 
Sometimes before I build a new ISAPI.DLL I'll tried some Ideas (2017), but after a few tries I build a new ISAPI.DLL with copy/paste from the last one.
 
But not this time. (2018) After some chatting with MVP Andrea Magni (MARS-Curiosity) and after some logging - i found the problem. Loadlibrary did not come back and crashes the AppPool. No Idea. Andrea provided me a Link. DLLMain - What? I have no DLLMain so I did not see the hint at the first read.
 
The hint was : do not call Loadlibrary in the Main-Thread. From my point of view every ISAPI.DLL is loaded by the IIS and with every request the IIS creates one thread of it.. So never in the Main-Thread.
 
After a few tries with LoadLibraryEx - I tried to compile my DLL's in 64Bit so this WOW thing is not necessary. LoadlibraryEx worked but no handle or a handle but nur GetProcAddress.
 
After some googleing for a new version of the Egg-Loader I came back to the Best-Practices Link and finally found "Call LoadLibrary or LoadLibraryEx (either directly or indirectly). This can cause a deadlock or a crash." OK - This is the problem - and perhaps same for the old egg-loader - and now?
 
Don't do this and don't do that - but how to load a DLL?
 

You remeber : NOT IN THE MAIN THREAD!

 
After a simple TTask.Run() around my Plugin-Loader everything works fine. Perhaps I will create a normal thread for this task. But for the moment it's working (that are the good news) - the bad news are : Now I'm able to build all that Stuff that is on my wish-list and I have no excuse not to do it) ;-)
 
But as always - not enough time.