14.1. Pools
The most important thing to understand about the Apache API is the
idea of a pool. This is a grouped collection of
resources (i.e., file handles, memory, child programs, sockets,
pipes, and so on) that are released when the pool is destroyed.
Almost all resources used within Apache reside in pools, and their
use should only be avoided with careful thought.
An interesting feature of pool resources is that many of them can be
released only by destroying the pool. Pools may contain subpools, and
subpools may contain subsubpools, and so on. When a pool is
destroyed, all its subpools are destroyed with it.
Naturally enough, Apache creates a pool at startup, from which all
other pools are derived. Configuration information is held in this
pool (so it is destroyed and created anew when the server is
restarted with a kill). The next level of pool is
created for each connection Apache receives and is destroyed at the
end of the connection. Since a connection can span several requests,
a new pool is created (and destroyed) for each request. In the
process of handling a request, various modules create their own
pools, and some also create subrequests, which are pushed through the
API machinery as if they were real requests. Each of these pools can
be accessed through the corresponding structures (i.e., the connect
structure, the request structure, and so on).
With this in mind, we can more clearly state when you should not use
a pool: when the lifetime of the resource in question does not match
the lifetime of a pool. If you need temporary storage (or files, or
whatever), you can create a subpool of a convenient pool (the request
pool is the most likely candidate) and destroy it when you are done,
so having a lifetime that is shorter than the pool's is not
normally a good enough excuse. The only example we can think of where
there is no appropriate pool is the code for handling listeners
(copy_listeners()
and
close_unused_listeners() in
http_main.c), which have a lifetime longer than
the topmost pool!
There are a number of advantages to this approach, the most obvious
being that modules can use resources without having to worry about
when and how to release them. This is particularly useful when Apache
handles an error condition. It simply bails out, destroying the pool
associated with the erroneous request, confident that everything will
be neatly cleaned up. Since each instance of Apache may handle many
requests, this functionality is vital to the reliability of the
server. Unsurprisingly, pools come into almost every aspect of
Apache's API, as we shall see in this chapter. They are defined
in alloc.h :
typedef struct pool pool;
The actual definition of struct
pool can be found in alloc.c,
but no module should ever need to use it. All modules ever see of a
pool is a pointer to it, which they then hand on to the pool APIs.
Like many other aspects of Apache, pools are configurable, in the
sense that you can add your own resource management to a pool, mainly
by registering cleanup functions (see the pool API later in this
chapter).