It is a TWebModule created for each request within a Delphi ISAPI DLL

825 views Asked by At

I´m writing a ISAPI application using Delphi. There are many tutorials over there, but no one goes beyond the classic OnAction/Response.Content example
The question is self explanatory. Does every request creates a new TWebModule instance? Once created, that TWebModule keeps handling requests for that connection?
Even Delphi documentation is vague. I´m trying to find a way to manage sessions inside the application but many details aren´t clear in the tutorials nor documentation, for example: is the DLL unloaded after a request is served? The "program" part of the DLL (the main begin/end. pair) is the DLL global initialization? Is a TWebModule created for each browser (for example the user trying to connect from two distinct browsers in the same computer)?
The application will be served from Apache 2.4 running on Windows 2012 R2

2

There are 2 answers

2
paulsm4 On

Delphi TWebModule wraps any of several different technologies, including either CGI or ISAPI. You seem to be interested in ISAPI.

Per the Microsoft documentation:

https://learn.microsoft.com/en-us/previous-versions/iis/6.0-sdk/ms525172(v=vs.90)

The following events occur when IIS receives a request that maps to an ISAPI extension:

  1. IIS loads the DLL, if it is not already in memory. When the DLL is loaded, Windows automatically calls the optional DLL entry/exit function (usually DllMain). IIS then calls the extension's GetExtensionVersion entry-point function.

  2. IIS performs minor preprocessing on the incoming request.

  3. IIS creates and populates an EXTENSION_CONTROL_BLOCK structure to pass request data and callback function pointers to the extension.

  4. IIS calls the ISAPI extension's HttpExtensionProc function, passing a pointer to the EXTENSION_CONTROL_BLOCK structure created for this request.

  5. The ISAPI extension carries out the actions it was designed to perform: for example, reading more data from the client (as in a POST operation), or writing headers and data back to the client.

  6. The extension informs IIS that it is finished processing the request by exiting the HttpExtensionProc function. For synchronous operations, the function returns the HSE_STATUS_SUCCESS return code; for asynchronous operations, the return code is HSE_STATUS_PENDING. For more information about asynchronous operations, see Asynchronous I/O Processing.

  7. IIS performs cleanup on the connection used for the request, after which it closes the connection if Keep-Alive functionality is not enabled.

  8. Once the ISAPI extension is no longer needed, IIS calls the TerminateExtension function, if the extension provides one. If IIS is configured to cache ISAPI extensions, TerminateExtension is not called until the IIS Web server is shut down or restarted.

So yes, the .dll is loaded once (per server), but connections are treated seperately (per client request).

0
alvaroc On

Short answer: not always, it depends
Medium answer: it depends on the browser, the web server and Delphi
Long answer:

  1. It depends on threads (or processes) on the browser. Suppose a page invokes three actions on your TWebModule, say three href, one for loading a image, another for a css and one more for a Javascript. The browser may or may not send the request at the same time. Most likely it will.
  2. It depends on the server. If it receives the requests at the same time (separated with a few discardable miliseconds), it may create multiple concurrent requests to your TWebModule or may serialize them, as paulsm4 described
  3. It depends on Delphi. Tracing the source code seems that it creates a new thread/TWebModule pair for each request. The module, however, it is kept for further reuse. It seems that his behaviour can be modified at runtime

Conclussion: TWebModules are not reliable for persistance management. It worked for me to create another kind of Datamodule, but:

 MyDataModule :=  TMyDataModule.Create(Application);   
// don´t use Application.CreateForm(MyDataModule)  

Inside MyDataModule, persistance can be handled. It won´t be created, discarded nor modified by Delphi.
P.D. Theoretically, any ISAPI DLL can be unloaded by the server at any time. Apache has a directive por keeping it: ISAPICacheFile. Unloading the DLL however, seems to defeat the purpouse of ISAPI for improving the CGI overhead.