Login   Register  
PHP Classes
elePHPant
Icontem

File: daemon.class.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  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: 8 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_pidSIGTERM);
        @
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_pidSIGCONT);
    }
}

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

//end of the class
}

?>