|
|
LXXXII. Process Control FunctionsIntroductie
Process Control support in PHP implements the Unix style of
process creation, program execution, signal handling and process
termination. Process Control should not be enabled within a
webserver environment and unexpected results may happen if any
Process Control functions are used within a webserver environment.
This documentation is intended to explain the general usage of
each of the Process Control functions. For detailed information
about Unix process control you are encouraged to consult your
systems documentation including fork(2), waitpid(2) and signal(2)
or a comprehensive reference such as Advanced Programming in the
UNIX Environment by W. Richard Stevens (Addison-Wesley).
PCNTL now uses ticks as the signal handle callback mechanism, which is
much faster than the previous mechanism. This change follows the same
semantics as using "user ticks". You use the declare()
statement to specify the locations in your program where callbacks are
allowed to occur. This allows you to minimize the overhead of handling
asynchronous events. In the past, compiling PHP with pcntl enabled would
always incur this overhead, whether or not your script actually used
pcntl.
There is one adjustment that all pcntl scripts prior to PHP 4.3.0 must
make for them to work which is to either to use
declare() on a section where you wish to allow
callbacks or to just enable it across the entire script using
the new global syntax of declare().
Opmerking: Deze module is niet verkrijgbaar voor de
windows versie van PHP.
AfhankelijkhedenDeze functies zijn beschikbaar als onderdeel van
de standarad module die altijd beschikbaar is. Installatie
Process Control support in PHP is not enabled by default.
You have to compile the CGI or CLI version of PHP with
--enable-pcntl configuration
option when compiling PHP to enable Process Control support.
Opmerking:
Currently, this module will not function on non-Unix platforms
(Windows).
Configuratie tijdens scriptuitvoerDeze extensie gebruikt geen configuratie regels. Resource typesDeze extensie maakt geen gebruik van resources. Voorgedefineerde constanten
The following list of signals are supported by the Process Control
functions. Please see your systems signal(7) man page for details
of the default behavior of these signals.
Voorbeelden
This example forks off a daemon process with a signal handler.
Voorbeeld 1. Process Control Example <?php
declare(ticks=1);
$pid = pcntl_fork();
if ($pid == -1) {
die("could not fork");
} else if ($pid) {
exit(); // we are the parent
} else {
// we are the child
}
// detatch from the controlling terminal
if (!posix_setsid()) {
die("could not detach from terminal");
}
// setup signal handlers
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGHUP, "sig_handler");
// loop forever performing tasks
while(1) {
// do something interesting here
}
function sig_handler($signo) {
switch($signo) {
case SIGTERM:
// handle shutdown tasks
exit;
break;
case SIGHUP:
// handle restart tasks
break;
default:
// handle all other signals
}
}
?> |
|
User Contributed Notes Process Control Functions |
add a note |
rfrew at mxm dot com
22-Feb-2002 10:59 |
|
If you use Zend Optimizer 1.20, it is not compatible with PCNTL. You'll
get an error message stating: '[Zend Optimizer] Zend Optimizer 1.2.0 is
incompatible with pcntl 1.0 in Unknown on line 0'.
You get this
error message when you compile using the --enable-pcntl option.
|
|
daniel[at]lorch.cc
27-Feb-2002 10:48 |
|
This piece of code helped me to find out what signals are being sent to my
process:
function sig_identify($signo) { switch($signo) {
case SIGFPE: return 'SIGFPE'; case SIGSTOP: return
'SIGSTOP'; case SIGHUP: return 'SIGHUP'; case SIGINT:
return 'SIGINT'; case SIGQUIT: return 'SIGQUIT'; case
SIGILL: return 'SIGILL'; case SIGTRAP: return 'SIGTRAP';
case SIGABRT: return 'SIGABRT'; case SIGIOT: return
'SIGIOT'; case SIGBUS: return 'SIGBUS'; case SIGPOLL:
return 'SIGPOLL'; case SIGSYS: return 'SIGSYS'; case
SIGCONT: return 'SIGCONT'; case SIGUSR1: return 'SIGUSR1';
case SIGUSR2: return 'SIGUSR2'; case SIGSEGV: return
'SIGSEGV'; case SIGPIPE: return 'SIGPIPE'; case SIGALRM:
return 'SIGALRM'; case SIGTERM: return 'SIGTERM'; case
SIGSTKFLT: return 'SIGSTKFLT'; case SIGCHLD: return
'SIGCHLD'; case SIGCLD: return 'SIGCLD'; case SIGIO:
return 'SIGIO'; case SIGKILL: return 'SIGKILL'; case
SIGTSTP: return 'SIGTSTP'; case SIGTTIN: return 'SIGTTIN';
case SIGTTOU: return 'SIGTTOU'; case SIGURG: return
'SIGURG'; case SIGXCPU: return 'SIGXCPU'; case SIGXFSZ:
return 'SIGXFSZ'; case SIGVTALRM: return 'SIGVTALRM'; case
SIGPROF: return 'SIGPROF'; case SIGWINCH: return 'SIGWINCH';
case SIGPWR: return 'SIGPWR'; } }
function
sig_handler($signo) { echo "Caught " . sig_identify($signo)
. " (" . $signo . ") on " . posix_getpid() .
"\n"; }
pcntl_signal(SIGFPE,
"sig_handler"); pcntl_signal(SIGHUP,
"sig_handler"); // pcntl_signal(SIGINT,
"sig_handler"); pcntl_signal(SIGQUIT,
"sig_handler"); pcntl_signal(SIGILL,
"sig_handler"); pcntl_signal(SIGTRAP,
"sig_handler"); pcntl_signal(SIGABRT,
"sig_handler"); pcntl_signal(SIGIOT,
"sig_handler"); pcntl_signal(SIGBUS,
"sig_handler"); pcntl_signal(SIGPOLL,
"sig_handler"); pcntl_signal(SIGSYS,
"sig_handler"); pcntl_signal(SIGCONT,
"sig_handler"); pcntl_signal(SIGUSR1,
"sig_handler"); pcntl_signal(SIGUSR2,
"sig_handler"); pcntl_signal(SIGSEGV,
"sig_handler"); pcntl_signal(SIGPIPE,
"sig_handler"); pcntl_signal(SIGALRM,
"sig_handler"); pcntl_signal(SIGTERM,
"sig_handler"); pcntl_signal(SIGSTKFLT,
"sig_handler"); pcntl_signal(SIGCHLD,
"sig_handler"); pcntl_signal(SIGCLD,
"sig_handler"); pcntl_signal(SIGIO,
"sig_handler"); pcntl_signal(SIGTSTP,
"sig_handler"); pcntl_signal(SIGTTIN,
"sig_handler"); pcntl_signal(SIGTTOU,
"sig_handler"); pcntl_signal(SIGURG,
"sig_handler"); pcntl_signal(SIGXCPU,
"sig_handler"); pcntl_signal(SIGXFSZ,
"sig_handler"); pcntl_signal(SIGVTALRM,
"sig_handler"); pcntl_signal(SIGPROF,
"sig_handler"); pcntl_signal(SIGWINCH,
"sig_handler"); pcntl_signal(SIGPWR,
"sig_handler");
I commented out SIGNIT, as it is the
signal which is sent to your process when you press CTRL-C. If you catch
this signal, you must handle it properly:
function
sig_handler($signo) { switch($signo) { case SIGINT:
// customized cleanup code exit; // now exit break;
} }
Otherwise the only possibility to stop your process is by
sending a SIGKILL signal - you can do this on the shell by typing
"kill -9 PID" (where -9 is the numerical value for
SIGKILL).
Note: You cannot add a handler (i.e. ignore signals) for
SIGSTOP and SIGKILL - for obvious reasons.
|
|
christophe dot dirac at swissphone dot ch
27-May-2002 10:42 |
|
The signal handler pcntl_signal() does not work if you are waiting for
socket connections with socket_accept(). The signal handler
is installed, but does not do anything if a signal arrives. Anyone
got a solution for that?
|
|
keksov[at]gmx.de
29-May-2002 05:10 |
|
You have to use socket_select before socket_accept, so your code will wait
for connection with select. socket_select can be interrupted by signals
easily. Below is an example from my library (methods of class
TNetSocket): //-- select function
select($aread=NULL,$awrite=NULL,$aexcept=NULL,$timeout=NULL) {
while(1) { $res="";
$res=socket_select($aread, $awrite, $aexcept, $timeout);
//
if errno===0 it means what select was interrrupted by SysV signal
if($res===false && socket_last_error($this->socket())!==0)
{ // error occured, interrupted not by a signal
$this->set_socket_error(__LINE__); return(false);
} break; } return(true); }
//--
accept, wait for incomming connection function accept() {
$this->clear_socket_error();
$this->set_io_socket(_SOCKET_);
$socket=$this->socket(); $aread=array($socket); if
($this->select($a=&$aread)===false) return(false);
$child_socket=socket_accept($this->socket); if($child_socket
<= 0) { // error occured
$this->set_socket_error(__LINE__); return(false);
}
$this->child_socket=$child_socket;
$this->sockets[_CHILD_SOCKET_]=&$this->child_socket;
$this->set_io_socket(_CHILD_SOCKET_);
$a=&$this->peername;
$res=socket_getpeername($child_socket,$a);
if($res <= 0)
{ // error occured $this->set_socket_error(__LINE__);
return(false); }
$this->get_address_and_port(_CHILD_SOCKET_);
TLogManager::phpserv("Connection accepted. ADDRESS $this->address,
PORT
$this->port","net_socket",__FILE__,__LINE__);
$this->connected=true; return(true); // return new object of
TNetSocket type }
|
|
van[at]webfreshener[dot]com
11-Oct-2002 02:53 |
|
Forking your PHP daemon will cause it to zombie on exit.
...or so
I've seen on: FreeBSD (PHP4.2.x) Debian (PHP4.3.0-dev) Darwin
(PHP4.3.0-dev)
This was tested with the example code above and
other scripts created for evaluation.
Seems adding
<b>--enable-sigchild</b> to your configure will get rid of the
problem.
Hope that saves some hair tearing :]
|
|
add a note |
| |