Share via


ISAPI Extension Design Issues

This topic provides information about issues that should be considered when designing ISAPI extensions.

Process Isolation

Because the ISAPI extension DLL is loaded into the same process as IIS, a possibility exists that access violations and other bugs in the ISAPI extension code could cause IIS to crash. Therefore, all ISAPI extensions should be thoroughly tested to ensure integrity. One way of doing this is to make such suspect DLLs run in a separate process by placing the extension in an application marked as out-of-process. Doing this causes IIS to use its process isolation technique, which executes the ISAPI DLL outside of the main IIS process. IIS also performs crash detection and recovery for such exterior processes.

State Maintenance

General state initialization for an ISAPI extension can occur in the entry-point function GetExtensionVersion. Alternatively, it can occur in the optional DLL entry/exit function (usually DllMain), using Visual C++. Like any Win32 DLL, provided DLL entry/exit functions are called by the C run-time library when the extension is first loaded, when it is unloaded by IIS, and whenever a new thread (other than the primary thread) is created or destroyed in the process.

It is good practice to maintain statistical information, or any information pertaining to the DLL, within the DLL itself. By creating the appropriate forms, it is possible to measure the usage and performance of a DLL remotely; this information can be integrated with the system performance counters and then with SysMon. Also, the lpszLogData member of the EXTENSION_CONTROL_BLOCK structure can be used to record data with the server log.

Language and Framework Choice

The IIS SDK assumes the use of either C or C++ as the development language, and that the Microsoft Foundation Class (MFC) library is not in use. The MFC library provides an object model, as well as a wizard, that can be useful in creating ISAPI extensions. Classes such as CHttpServer, CHttpServerContext, and CHtmlStream are provided. For more information about MFC, see the MFC library and the Visual C++ SDK.

Thread-Safe Design and Thread Synchronization

Because all (in-process) requests are handled by the same DLL mapped into the IIS process space, an ISAPI extension must be designed and implemented with appropriate thread-safe procedures and structures. This is especially important if the extension relies on global state information or structures, such as worker-thread work queues.

The operating system serializes calls to the DLL entry/exit function DllMain. Due to potentially troublesome interactions with the thread synchronization used to accomplish this serialization, it is best to avoid using or requiring thread synchronization mechanisms (including the various Win32 WaitFor... functions) within DllMain.

For information about writing multithread-safe DLLs, see Processes and Threads in the Platform SDK, or any advanced book on Win32 programming.

Reporting an Unhealthy State

An ISAPI extension application can be built to programmatically signal to IIS that it needs to be recycled. This can be accomplished with the new ServerSupportFunction function HSE_REQ_REPORT_UNHEALTHY. Note that this level of programming is specific to the ISAPI programming interface; ASP or ASP.NET code would not implement this type of logic. This feature is available only to ISAPI extensions running in worker process isolation mode.

To use HSE_REQ_REPORT_UNHEALTHY effectively, the IIS server that is running the application must have process pinging enabled, as it is during the ping operation that WAS also checks to see if ISAPI has signaled its unhealthy state. ISAPI must implement some internal mechanism for determining its unhealthy state, such as monitoring the status of its internal thread pool.

Note

This type of programming shuts down the worker process in which the ISAPI extension is running. Therefore, all applications running in that worker process are restarted. The ASP ISAPI extension implements logic that takes advantage of this feature as it monitors the status of its internal thread pool. If too many of its threads enter a blocking state, it signals a recycle.

The following code example demonstrates the use of HSE_REQ_REPORT_UNHEALTHY.

DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB) 
{ 
  // ... 

  fResult = pECB->ServerSupportFunction( 
    pECB->ConnID, 
    HSE_REQ_REPORT_UNHEALTHY, 
    szReason, 
    NULL, 
    NULL); 

  // ...   
} 

VectorSend (HSE_REQ_VECTOR_SEND) Function

In IIS versions prior to 6.0, there are two ways of handling a response made up of multiple buffers: by calling the WriteClient function multiple times, or by assembling the response in a single large buffer. The first approach results in performance degradation because there is one kernel mode transition per buffer. The second approach also has a performance cost, and requires additional memory.

The response of a custom ISAPI extension always consists of a header, some static content, and possibly a database query and a footer. In IIS 6.0, the entire response can be sent in one call to the HSE_REQ_VECTOR_SENDServerSupportFunction function. It is also possible to send a vector of chunks to the client without calling WriteClient multiple times. HSE_REQ_VECTOR_SEND allows the developer to put together a list of buffers and file handles to send in order and then hand off to IIS for compilation into the final response. HTTP.sys compiles all of the buffers and/or file handles into a single response buffer within the kernel and then sends it. This frees ISAPI from the necessity of buffer construction or multiple calls to WriteClient.