cliProcessControls

Provides POSIX control functions for daemon processes. This set of methods is for forking processes. It will create PID files (a text file containing the process ID) on successful launch of the process.

WARNING: Under no circumstance should this class be extended or the methods used in an object oriented manner. cliProcessControls::daemonise() must be called exactly as typed otherwise the fork process will not complete correctly. At the time of writing, making these class functions does not re-map the memory properly or at least causes problems where the child process and the parent process are not properly separated.

WARNING: to be able to daemonise in this system you must have root access to the server as the daemonising code attempts to reset the session leader to another user - the forked processes do NOT run as root but as the framework configured user, usually a system account or user account with no shell access and that has no group etc.

These methods should be used in the following manner:

// example for PHP <5.3
require_once(dirname(dirname(__FILE__)).'/libraries/system.inc');
declare(ticks=1);

class myDaemon extends cliDaemon {
    // my daemon code
    function execute() {
        do {
            // myDaemon does something interesting / cool here
        } while ( $loop === true ); 
    }
}

// get cli params, required for app
$oRequest = cliRequest::getInstance();

// Initialise process control
cliProcessControls::initialise($oRequest, 'myDaemon');

//Attempt to daemonise process
cliProcessControls::daemonise();

$oDaemon = new myDaemon();
$oDaemon->setPosixId(cliProcessControls::getPosixId());
$oDaemon->setPidFile(cliProcessControls::getPidFile());
$oDaemon->setPosixUser(system::getConfig()->getSystemUser());
$oDaemon->setPosixGroup(system::getConfig()->getSystemGroup());
$oDaemon->trapSignal(SIGINT, SIGHUP, SIGTERM);
$oDaemon->getListeners()->attachListener(new cliApplicationListenerLog());
$oDaemon->execute();

While PHP in web processes has pretty good resource usage (memory leaks are rare), long running processes can have a lot of issues. It is vital that before any production use a daemon is tested in a staging environment under load for at least a few days to make sure there are no hidden leaks.

Things that can help reduce memory leaks:

With careful coding there is no reason why PHP cannot be used in this manner. From my own experience, I have had PHP daemon processes running for months without any issues at all.

Additional Notes: PHP 5.3+ deprecates the use of declare(ticks=1); This means that the above example will not function correctly as the signal handler can only be installed with ticks. The PHP docs have not been updated yet to provide instructions on a solution. Fortunately a post to the bug list: pcntl_signal needs declare(ticks) which is deprecated since 5.3 offers a solution. Instead of looping: while ( $loop === true ); it needs to be modified to add a call to: pcntl_signal_dispatch. This will then fire all attached signal handlers.


Methods

private __construct()

Throw exception, preventing class being instantiated

public static getCliRequest()

Returns the instance of cliRequest

public static setCliRequest($inRequest)

Sets the instance of cliRequest

public static getPidFile()

Return the current pidFile

public static setPidFile($inPidFile)

Set pidFile to static vars

public static getPosixId()

Return the current posix process ID

public static setPosixId($inPosixId)

Set posixId to static vars

public static getChildProcesses()

Returns array of child process IDs

public static initialise($inCliRequest, $inClassname)

Installs signal handlers for $inClassname, should be called before daemonising

public static daemonise()

Turn our script into a daemon

public static fork()

Fork the current process and create a child process

public static createPidFile([$inPidFile = false], [$inProcessID = false])

Creates a process ID file for the daemon

public static hasPidFile()

Checks to see if a PID file has been creasted already

public static deletePidFile()

Deletes a PID file if it exists

<  1  >