Temp1ar
Новичок
Закрытие дочерних и главных процессов, pcntl_fork
Помогите пожалуйста с процессами разобраться. Ситуация следущая. Скрипт работает на ура, но при попытке завершить процесс в Linux командой kill, он ни как не реагирует и продолжает работу. По сути это многопоточный телнет сервер, создающий дочерний процесс для каждого клиента. При отключении клиента, созданный процесс получает стату Z (zombie) и приписку <defunct>. Читал документации по PCNTL и не понял как его убивать.
1. Как автоматически убивать подпроцесс при отключении клиента?
2. Как сделать главный процесс убиваемым(если имеются подпроцессы, они тоже должны быть убиты)?
Исходник(запускаю su; php script.php); Многое взято с примеров php.net.
PS: перечитал форум по форкам, но не могу выродить эти пару строчек проверки...
Помогите пожалуйста с процессами разобраться. Ситуация следущая. Скрипт работает на ура, но при попытке завершить процесс в Linux командой kill, он ни как не реагирует и продолжает работу. По сути это многопоточный телнет сервер, создающий дочерний процесс для каждого клиента. При отключении клиента, созданный процесс получает стату Z (zombie) и приписку <defunct>. Читал документации по PCNTL и не понял как его убивать.
1. Как автоматически убивать подпроцесс при отключении клиента?
2. Как сделать главный процесс убиваемым(если имеются подпроцессы, они тоже должны быть убиты)?
Исходник(запускаю su; php script.php); Многое взято с примеров php.net.
PS: перечитал форум по форкам, но не могу выродить эти пару строчек проверки...
PHP:
#!/usr/local/bin/php -q
<?php
error_reporting (4);
set_time_limit (0);
ob_implicit_flush();
$pid_file = '/tmp/php_daemon.pid';
$underpriv_uid = '99'; // uid 99 == user nobody, at least on my system.
$underpriv_gid = '99';
$port = 10000;
$address = 0; // 0 binds to all addresses, may not work on fbsd
$quit = 0;
$logtofile = TRUE;
function sig_handler($signo) {
switch($signo) {
case SIGTERM:
// handle shutdown tasks
exit;
break;
case SIGHUP:
// handle restart tasks
break;
case SIGUSR1:
print "Caught SIGUSR1...\n";
break;
case SIGCHLD:
while( pcntl_waitpid(-1, $status, WNOHANG) > 0 )
{ \* Вот суда что-то надо вставить, мне кажется *\};
break;
case SIGINT:
exit;
default:
// not implemented yet...
break;
}
}
pcntl_signal(SIGCHLD, "sig_handler");
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGINT, "sig_handler");
function readtobuffer($msgsock) {
if (false === ($buf = socket_read($msgsock, 2048, PHP_NORMAL_READ))) {
logi ("Client disconnected" .
socket_strerror(socket_last_error($msgsock)) . "\n");
socket_shutdown($msgsock, 2);
socket_close($msgsock);
exit;
break 3;
}
return $buf;
}
function logi($mess){
global $obj;
echo "[".date("d.m.Y H:i:s")."]: ".$mess."\n\r";
}
function shutdown(){
logi("Shutdown command sended");
unlink($pid_file);
exit;
}
function interact($msgsock) {
do {
$msg = "Hello maaaan\n";
socket_write($msgsock, $msg, strlen($msg));
do {
$buf=readtobuffer($msgsock);
if (!$buf = trim($buf)) continue;
execute($buf,$msgsock);
} while (true);
socket_close($msgsock);
} while (true);
}
function execute($buf, $msgsock)
{
# Обработка комманд
if ($buf=="shutdown") exit;
}
function become_daemon() {
$child = pcntl_fork();
if($child) {
exit; // kill parent
}
posix_setsid(); // become session leader
chdir("/");
umask(0); // clear umask
return posix_getpid();
}
function open_pid_file($file) {
if(file_exists($file)) {
$fp = fopen($file,"r");
$pid = fgets($fp,1024);
fclose($fp);
if(posix_kill($pid,0)) {
print "Server already running with PID: $pid\n";
exit;
}
print "Removing PID file for defunct server process $pid\n";
if(!unlink($file)) {
print "Cannot unlink PID file $file\n";
exit;
}
}
if($fp = fopen($file,"w")) {
return $fp;
} else {
print "Unable to open PID file $file for writing...\n";
exit;
}
}
function change_identity($uid,$gid) {
global $pid_file;
if(!posix_setgid($gid)) {
print "Unable to setgid to $gid!\n";
unlink($pid_file);
exit;
}
if(!posix_setuid($uid)) {
print "Unable to setuid to $uid!\n";
unlink($pid_file);
exit;
}
}
$fh = open_pid_file($pid_file);
if (($sock = socket_create (AF_INET, SOCK_STREAM, 0)) < 0) {
print "socket_create() failed: reason: " . socket_strerror ($sock) . "\n";}
if (($ret = socket_bind ($sock, $address, $port)) < 0) {
print "socket_bind() failed: reason: " . socket_strerror ($ret) . "\n";}
if (($ret = socket_listen ($sock, 0)) < 0) {
print "socket_listen() failed: reason: " . socket_strerror ($ret) . "\n";
}
change_identity($underpriv_uid,$underpriv_gid);
print "Server ready. Waiting for connections.....\n";
$pid = become_daemon();
fputs($fh,$pid);
fclose($fh);
while (!$quit) {
if (($connection = socket_accept($sock)) < 0) next;
if( ($child = pcntl_fork()) == -1 ) {
print "Could not fork!!\n";
print "Dying...\n";
$quit++;
}
elseif($child == 0) {
socket_close($sock);
interact($connection);
exit;
}
socket_close($connection);
}
if(posix_getpid() == $pid) {
unlink($pid_file);
}