PHP Classes

File: daemon.class.php

Recommend this page to a friend!
  Classes of Grigori Kochanov   Daemon Emulation   daemon.class.php   Download  
File: daemon.class.php
Role: Class source
Content type: text/plain
Description: The class that allows to make script a daemon process
Class: Daemon Emulation
Create and manage daemon processes
Author: By
Last change: added author info and requirements
Date: 17 years ago
Size: 3,739 bytes
 

Contents

Class file image Download
<?php
/* This code is writed by Grigori A. Kochanov.
* The script can be used, modified and redistributed freely
* under the terms and conditions of the BSD public license.
*
* Requirements: PHP 5 CLI compiled with --enable-pcntl, POSIX functions not disabled
* UNIX-style systems only
*
* version: 1
*/

class Daemon{

//show demonstration messages
const DEBUG_MODE = true;

//exit if sleeping more then MAX_SLEEP_HOURS
const MAX_SLEEP_HOURS = 6;

//path to the pid file
const PID_FILE_PATH='daemon.pid';

//service parameters
const i_sleep = 1;
const
i_run = 2;
const
i_exit = 3;
private
$role;
private
$child_pid;

/**
 * Checks the configuration, register signal handler and start the multi-process daemon emulation
 *
 */
public function __construct(){
   
//check the PHP configuration
   
if (!defined('SIGHUP')){
       
trigger_error('PHP is compiled without --enable-pcntl directive',E_USER_ERROR);
    }
   
//check if the pid file is writable
   
if (file_exists(self::PID_FILE_PATH ) && !is_writable(self::PID_FILE_PATH) ||
        !
file_exists(self::PID_FILE_PATH ) && !is_writable(dirname(self::PID_FILE_PATH))
    ){
       
trigger_error('can not open PID file '.self::PID_FILE_PATH.' for writing', E_USER_ERROR);
    }
   
   
// tick required as of PHP 4.3.0
   
declare(ticks = 2);

   
// setup signal handlers
   
pcntl_signal(SIGTERM,array($this,'sigTermHandler'));
   
pcntl_signal(SIGCONT,array($this,'sigContHandler'));
   
pcntl_signal(SIGALRM,array($this,'sigAlrmHandler'));
   
   
//register the shutdown function to waken the child
   
register_shutdown_function(array($this,'wakeUpChild'));

   
//the parent will work
   
$this->role = self::i_run;
   
    if (
self::DEBUG_MODE){
        echo
"Root PID: ".posix_getpid()."\n";
    }
    do{
       
//child sleeps
       
if ($this->role == self::i_sleep ){
            if (
self::DEBUG_MODE){
                echo
'process ', $pid," will sleep\n";
            }
           
sleep(0xFFFFFFFF);
        }
       
       
//if we are asked to exit - let's do it
       
if ($this->role == self::i_exit ){
            @
unlink(self::PID_FILE_PATH );
            exit;
        }
        if (
$this->role == self::i_run){
           
//spawn a child and continue the work
           
$this->child_pid = pcntl_fork();
           
$pid = posix_getpid();
            if (!
$this->child_pid){
               
//it's a child - go to bed
               
$this->role = self::i_sleep;
               
pcntl_alarm(3600*self::MAX_SLEEP_HOURS); // max time to sleep, then exit
           
}
        }
    }while (
$this->role == self::i_sleep);

   
//write the PID
   
file_put_contents(self::PID_FILE_PATH,$pid);

    if (
self::DEBUG_MODE){
        echo
'process ',$pid, " continues opertions\n";
    }
}

/**
 * Catch the SIGTERM signal
 *
 */
private function sigTermHandler(){
    if (
self::DEBUG_MODE){
        echo
"SIGTERM CAUGHT\n";
    }
   
// I was asked to exit - pass the call to the child and remove the PID file
   
if ($this->child_pid){
       
posix_kill($this->child_pid, SIGTERM);
        @
unlink(self::PID_FILE_PATH );
    }
    exit;
}

/**
 * Catch the SIGCONT signal
 *
 */
private function sigContHandler(){
   
// I am waken up to run
   
$this->role = self::i_run;
}

/**
 * Catch the SIGALRM signal
 *
 */
private function sigAlrmHandler(){
   
//time is out
   
$this->role = self::i_exit;
}

/**
 * Send the signal to a child to wake him up to continue the work
 *
 */
public function wakeUpChild(){
    if (
$this->child_pid){
       
posix_kill($this->child_pid, SIGCONT);
    }
}

/**
 * Send the SIGTERM to the process and the child
 *
 */
public function terminate(){
   
posix_kill(posix_getpid(), SIGTERM);
}

//end of the class
}

?>