ProFTPD Developer's Guide: Resource Pools

ProFTPD Version 1.2

Table of Contents

Resource Pools

The primitive for creating a subpool is make_sub_pool, which takes another pool - the parent pool - as an argument. When the main pool is cleared, the subpool will be destroyed. The subpool may also be destroyed at any time, by calling the function destroy_pool(). This function will deallocate the entire pool.


  config_rec *c = NULL;
  pool *subpool = NULL;

  subpool = make_sub_pool(parent_pool);
  c = (config_rec *) pcalloc(subpool, sizeof(config_rec));
  c->pool = subpool;

As you can see, you allocate a subpool first, then allocate the object (in this case, a config_rec) from that subpool. You then store the pointer to the subpool in the appropriate field of the allocated object, so that later, when that object is no longer needed, you can do

which will take care of the entire object.

If you make your own subpool, be sure to call destroy_pool() once you are completely finished with your subpool. As when using malloc() and free(), if you allocate your own subpools, then you are responsible for cleaning up after yourself. Well, this not precisely the case; when your parent pool is destroyed, any subpools allocated from it, including your subpool, will be destroyed as well.

On rare occasions, too-free use of palloc() and the associated primitives may result in undesirably profligate resource allocation. You can deal with such a case by creating a subpool, allocating within the subpool rather than the main pool, and clearing or destroying the subpool, which releases the resources which were associated with it. This really is a rare situation; the only case in which it comes up in the standard module set is in case of listing directories, and then only with very large directories. Unnecessary use of the primitives discussed here can hair up your code quite a bit, with very little gain.

Most Frequently Used Pools
The following are pools that already exist in the most common structures within ProFTPD, and should be used for most purposes.

Never ever ever allocate memory directly from permanent_pool using one of the p*() pool functions listed below. Instead, make a subpool, do what you need to, and clear or destroy that subpool. permanent_pool only gets cleared rarely, on SIGHUP and shutdown. Abuse of this pool will lead to memory leaks.

Allocated: in init_alloc(), when the master daemon first starts up, or catches a SIGHUP

Deallocated: automatically, when the master daemon calls _exit()


Allocated: in start_new_server(), which is called if a <VirtualHost> section is encountered as the master parses the configuration file. As a special case, the main_server variable, the default "main" server, is allocated in init_config().

Deallocated: when forking a new server to handle an incoming connection, that connection is handed the appropriate server_rec, and all other server_recs are destroyed. This occurs in the forked child's process space, though; this prevents inter-server communication among concurrent connections.
This pool is also deallocated if a SIGHUP signal is received by the master daemon, all server_rec->pools are destroyed in main_rehash().


Allocated: this pool is not actually allocated, rather it is set using the same pointer to permanent_pool when the session starts, in fork_server(). This usage of the permanent_pool pointer is an exception to the normal rules of pool usage. In this case, however, this pointer assignment occurs after the process has forked, meaning that parent process' allocated heap memory (along with the rest of the process image) is duplicated. It is this duplicated memory space that the child process, via session_t->pool, is accessing, and not the long-running (if using "ServerType standalone") master daemon's permanent_pool.

Deallocated: this pool, being a duplicate of, and not synonymous with, permanent_pool, is deallocated when the child process exits.


Allocated: in the cmd_rnfr command handler, and the _data_new_xfer() function.

Deallocated: in cmd_rnto command handler, if session.xfer.path has not been set, if an error occurred during the renaming of the file, or if the renaming succeeded. Also, in cmd_rnfr(), prior to reallocating the same pool, to clear out any previous use. And similarly in _data_new_xfer(), prior to reallocating the same pointer, to clear out previous usage.
in data_cleanup(), and in data_abort() -- see comment in code for these two functions.


Allocated: in either inet_initialize_connection(), a static function (need to track when this is called -- I think by inet_create_connection, but why different from inet_copy_connection?), or in inet_copy_connection().

Deallocated: in inet_close(), when a connection is done.


Allocated: in add_config_set(), called by the add_config_*() functions. The parent pool is that of the containing server_rec's set, at the time when the configuration directive was parsed.

Deallocated: in remove_config(), or when the containing server_rec's pool is destroyed.


Allocated: for configuration directives, this allocation occurs in get_config_cmd(), after a line has been read from the configuration file but before that configuration command has been dispatched to its configuration handler. For commands, the allocation occurs in cmd_loop(), before dispatching to the appropriate command handler.

Deallocated: for configuration directives, this happens in parse_config_file(), after the configuration handler has returned. And, for commands, it happens in cmd_loop() after the command handler dispatch has returned.

  • cmd_rec->tmp_pool
    Allocated: this occurs, for commands, in _dispatch(), prior to the call to log_add_run() and the call to call_module_cmd(), which does the "dispatch" of the command to its handler(s). call_module() will also allocate this pool, if it is not already present.

    Deallocated: in _dispatch(), after the command handler has returned, and after any possible handler errors are dealt with.

    Pool Functions

    Table of Contents

    Author: $Author: castaglia $
    Last Updated: $Date: 2003/01/02 17:39:35 $

    © Copyright 2000-2003 TJ Saunders
    All Rights Reserved