httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Bill Stoddard" <>
Subject Re: Windows 2.0 MPM design issues
Date Wed, 31 May 2000 13:52:14 GMT

> MPM's are how the server maps a request to an execution
> primitive.  Basically, the server starts configures itself and calls the
> MPM code.
> The MPM is responsible for starting child processes and monitoring
> them.  It is also responsible for starting threads within the child
> process and having those threads (whether there be 1 or more) accept on
> the socket.  Once a request is made, the MPM is responsible for having an
> execution primitive handle the request.  For all of the current MPM's the
> same primitive that accepted the connection also handles request, however
> it would be possible to have one thread accept all connections and hand
> the requests off to other threads to actuall serve the request.
> LAstly, the MPM is responsible for managing the threads and other child
> processes.  And killing them when a restart/shutdown is requested.

Very good MPM overview. Continue with Win32 specific MPM details...

The WIN32 MPM creates two processes. The parent process and the parent process creates a child
process. The child process is multithreaded and is responsible for processing all HTTP requests.

The parent process:
1. Creates the AcceptEx IO Completion Port (IOCP for short) (I won't attempt explain this.
I'd take
too many words)
2. Opens all the listen sockets
3. Creates the child process
4. Passes a duplicated IOCP handle to the child (parent communicates to the child via pipe,
shared memory)
5. Passed duplicated listen socket handles to the child (via a pipe)
6. Waits for a restart or shutdown event (from an external process) or a child exit (normal
7. When one of the above events is signaled, the parent does the right thing (restarts the
child process, signals the child process to die gracefully and optionally on restart, restarts
a new
child process to take the place of the old child process.)
8. Thats it! The parent process job is very simple.

Steps 1, 2, 4 & 5 could be done directly in the child process. Doing them in the parent
allows the sockets (and pending connections in the listen queue) to be maintained across a
restart. Doing these steps in the child process would cause all pending connections to be
across a restart.

The main thread in the child process:
1. Receives the IOCP and duplicated sockets
2. Does initialization required to begin accepting connections
3. Creates a pool of worker threads which accept requests off the listen sockets (the details
a bitr depending on whether you are on NT or not). When a connection is received, a thread
the connection and processes the request that comes in on that connection.
4. Starts accepting requests
    95/98 requests are accepted on a seperate thread. NT uses an IOCP.
5. The main child thread then waits for a shutdown event (or on NT, a server maintenance event)

If the main thread received a server maintenance event, it does some IOCP magic to increase
number of connections that can be handled). When it receives a shutdown event (either generated
by a
worker thread or generated by the parent process), it shutdowns the worker threads gracefully
eventually exits.

There is a start_mutex which prevents more than one child process from accepting requests
at once.

The WIN32 MPM uses threads as the "execution primitive". Apache 1.3 on Windows used threads
as well.
The NT specific code uses IO Completion ports and does accepts asynchronously. Worker threads
dispatched off the IOCP in LIFO order, which is pretty cool. This is the first step to getting
to a
fully asynchronous server (which is my goal). What does this mean? Today the server is not
asynchronous, which means that you require 1 thread per concurrently connected client. 2000
concurrent clients implies the need for 2000 threads. Now threads are lighter weight than
but that still cost resources. A fully async server could handle those 2000 concurrent clients
1 thread (or realistically, a few threads) because that thread would NEVER block on network

Hope this helps.

Bill Stoddard

View raw message