By distributing the work across multiple processes, the process pool provides an effective way to avoid exceeding system-wide process limits on some platforms. Examples of such limits include the Solaris stdio file handle limit, and per-process heap address space limits on other platforms.
If you are using sendmail, the default behavior is to run each milter as a persistent pool of processes to cooperatively service connections from sendmail.
Process pooling is configured using the following settings in
pmx.conf (located by default in the
- max_pooled_procs = n: Instead of running each milter as a single multi-threaded process, PureMessage can start a persistent pool of processes to service connections for each milter. Setting this option to a non-zero value enables the process pool. The setting controls the maximum number of processes that the pool can contain. The default value is determined based on available memory. When the concurrency limit is reached and the process pool is enabled, PureMessage stops accepting connections on its port. Connections queue up until they overflow the TCP stacks listen queue, after which they are refused.
- min_pooled_procs = n: When the process pool is enabled, this option specifies how many processes should always be kept running. The default is 1.
- pooled_proc_idle_limit = na: Where a is either s (seconds), m (minutes), or h (hours) and n is the number of seconds, minutes or hours. When the process pool is enabled, this option specifies how long a process in the pool can stay idle before it goes away. The default is 5m.
- pooled_proc_connect_limit = n: When the process pool is enabled, this option specifies how many connections a process is allowed to handle before it terminates and a new process can take its place. The default is 0, which means that processes are not retired.
The PureMessage process pool is useful in at least three ways:
The top-level milter process monitors the pool for unexpected crashes or exits and restarts additional processes as necessary. This means the milter service has much better protection against crashes caused by temporary overload or resource constraints, through the ability to recover automatically when the overloaded or constrained resource conditions are removed.
Pre-forking a pool of persistent processes avoids the overhead of forking processes during each request, on platforms where support for threaded processing is not enabled.
Overcoming Arbitrary Process Limits
Some systems may have per-process resource limits that are small and cannot be changed. For example, for 32-bit programs using standard input and output, Solaris has a hard limit of 256 file handles that can be allocated by the stdio library within a single process. This in turn limits the number of threads that can be started in a single process, thereby limiting the number of concurrent connections that can be serviced by the milter. Starting a pool of processes, each of which can run a limited number of threads, overcomes such limits.