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).
There are a number of advantages to the pool 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. Their type is apr_pool_t, defined in
srclib/apr/include/apr_pools.h .
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 in
srclib/apr/include/apr_pools.h).
| | |
20.2. APR | | 20.4. Per-Server Configuration |