Overview
  • Namespace
  • Class
  • Tree

Namespaces

  • PHP
  • Yiinitializr
    • Cli
    • Clio
    • Composer
    • Helpers

Classes

  • Daemon
  1 <?php
  2 /**
  3  * Daemon class file.
  4  *
  5  * @author Antonio Ramirez <amigo.cobos@gmail.com>
  6  * @author Nofriandi Ramenta <nramenta@gmail.com>
  7  * @link http://www.ramirezcobos.com/
  8  * @link http://www.2amigos.us/
  9  * @link https://github.com/nramenta/clio
 10  * @copyright 2013 2amigOS! Consultation Group LLC
 11  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
 12  */
 13 namespace Yiinitializr\Clio;
 14 /**
 15  * Daemon  provides helpers for starting and killing daemonized processes
 16  *
 17  * @author Antonio Ramirez <amigo.cobos@gmail.com>
 18  * @package Yiinitializr.Cli
 19  * @since 1.0
 20  */
 21 class Daemon
 22 {
 23     /**
 24      * Daemonize a Closure object.
 25      * @param array $options Set of options
 26      * @param callable $callable Closure object to daemonize
 27      * @return bool True on success
 28      * @throws \Exception
 29      */
 30     public static function work(array $options, \Closure $callable)
 31     {
 32         if (!extension_loaded('pcntl')) {
 33             throw new \Exception('pcntl extension required');
 34         }
 35 
 36         if (!extension_loaded('posix')) {
 37             throw new \Exception('posix extension required');
 38         }
 39 
 40         if (!isset($options['pid'])) {
 41             throw new \Exception('pid not specified');
 42         }
 43 
 44         $options = $options + array(
 45             'stdin'  => '/dev/null',
 46             'stdout' => '/dev/null',
 47             'stderr' => 'php://stdout',
 48         );
 49 
 50         if (($lock = @fopen($options['pid'], 'c+')) === false) {
 51             throw new \Exception('unable to open pid file ' . $options['pid']);
 52         }
 53 
 54         if (!flock($lock, LOCK_EX | LOCK_NB)) {
 55             throw new \Exception('could not acquire lock for ' . $options['pid']);
 56         }
 57 
 58         switch ($pid = pcntl_fork()) {
 59             case -1:
 60                 throw new \Exception('unable to fork');
 61             case 0:
 62                 break;
 63             default:
 64                 fseek($lock, 0);
 65                 ftruncate($lock, 0);
 66                 fwrite($lock ,$pid);
 67                 fflush($lock);
 68                 return true;
 69         }
 70 
 71         if (posix_setsid() === -1) {
 72             throw new \Exception('failed to setsid');
 73         }
 74 
 75         fclose(STDIN);
 76         fclose(STDOUT);
 77         fclose(STDERR);
 78 
 79         if (!($stdin  = fopen($options['stdin'], 'r'))) {
 80             throw new \Exception('failed to open STDIN ' . $options['stdin']);
 81         }
 82 
 83         if (!($stdout = fopen($options['stdout'], 'w'))) {
 84             throw new \Exception('failed to open STDOUT ' . $options['stdout']);
 85         }
 86 
 87         if (!($stderr = fopen($options['stderr'], 'w'))) {
 88             throw new \Exception('failed to open STDERR ' . $options['stderr']);
 89         }
 90 
 91         pcntl_signal(SIGTSTP, SIG_IGN);
 92         pcntl_signal(SIGTTOU, SIG_IGN);
 93         pcntl_signal(SIGTTIN, SIG_IGN);
 94         pcntl_signal(SIGHUP,  SIG_IGN);
 95 
 96         call_user_func($callable, $stdin, $stdout, $stderr);
 97     }
 98 
 99     /**
100      * Whether a process is running or not
101      * @param $file
102      * @return bool
103      * @throws \Exception
104      */
105     public static function isRunning($file)
106     {
107         if (!extension_loaded('posix')) {
108             throw new \Exception('posix extension required');
109         }
110 
111         if (!is_readable($file)) {
112             return false;
113         }
114 
115         if (($lock = @fopen($file, 'c+')) === false) {
116             throw new \Exception('unable to open pid file ' . $file);
117         }
118 
119         if (flock($lock, LOCK_EX | LOCK_NB)) {
120             return false;
121         } else {
122             flock($lock, LOCK_UN);
123             return true;
124         }
125     }
126 
127     /**
128      * Kills a daemon process specified by its PID file.
129      *
130      * @param $file  Daemon PID file
131      * @param bool $delete Flag to delete PID file after killing
132      * @return bool  True on success, false otherwise
133      * @throws \Exception
134      */
135     public static function kill($file, $delete = false)
136     {
137         if (!extension_loaded('posix')) {
138             throw new \Exception('posix extension required');
139         }
140 
141         if (!is_readable($file)) {
142             throw new \Exception('unreadable pid file ' . $file);
143         }
144 
145         if (($lock = @fopen($file, 'c+')) === false) {
146             throw new \Exception('unable to open pid file ' . $file);
147         }
148 
149         if (flock($lock, LOCK_EX | LOCK_NB)) {
150             flock($lock, LOCK_UN);
151             throw new \Exception('process not running');
152         }
153 
154         $pid = fgets($lock);
155 
156         if (posix_kill($pid, SIGTERM)) {
157             if ($delete) unlink($file);
158             return true;
159         } else {
160             return false;
161         }
162     }
163 }
164 
API documentation generated by ApiGen 2.8.0