I am running a ISAPI service which runs with IdHTTPWebBrokerBridge
(for debugging as standalone EXE) as well as in Apache with mod_isapi
(in productive enviroment).
While logging some stuff at the destruction of the web module, I found following problem:
unit LogFactory;
...
initialization
GlobalLogFactory := TMyLogFactory.Create;
finalization
FreeAndNil(GlobalLogFactory);
end.
-
unit MyWebModuleUnit;
...
uses LogFactory;
procedure TMyWebModule.WebModuleDestroy(Sender: TObject);
begin
Assert(Assigned(GlobalLogFactory)); // <-- failure
GlobalLogFactory.GetLogger('D:\test.txt').LogLine('test'); // <-- Nullpointer Exception
end;
LogFactory.pas
creates the object GlobalLogFactory
on its initialization and destroys it on its finalization.
But LogFactory.pas:finalization
gets called BEFORE TMyWebModule.WebModuleDestroy
, since it was included by this unit only, and so the finalization will be done in reverse order.
How can I ensure that my GlobalLogFactory
will be correctly freed (i.e. FastMM will not warn about a memory leak), but at the same time, I want to give all destruction/finalization-procedures the chance to log something?
One Workaround would be to include LogFactory.pas
explicitely in the DPR file as the first unit. But I don't like that very much, since this Log-Unit should be used in many projects and it should be useable by simply including it in the unit where you need to log something. Putting this log unit in every DPR which might want to log something in future, is a big effort and forgetting it might cause problems for the developers who are not knowing what I did/require.
If you want
then you don't have many options. One option is to include the log unit very early in the .dpr file. I don't know why you regard that to be a problem. It's the standard way to achieve your goals. It's the technique used by external memory managers for example. Delphi developers are familiar with the concept. You tell the developers what they need to do, and if they don't follow your instructions, the program does not work. That is their problem.
If you still cannot face doing it this way then I see one alternative. Arrange for the logger initialization to happen before any other initialization in your code. And the finalization after all other finalization. You can do that by putting the logger implementation into an external module that is linked with load time linking.