Есть небольшой скрипт, который прослушивает порт.Когда кто-то подключен, процесс разветвляется.
Проблема в том, что когда дочерний процесс закрывается, он не закрывается правильно, а становится процессом зомби.
Также хочу добавить, что для меня важно, чтобы скрипт работал асинхронно и мог поддерживать несколько входящих соединений.
Как правильно завершить дочерние процессы в моем случае?
Ниже приведен код скрипта:
$serverSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($serverSocket=== false) {
echo 'socket_create() failed: reason: ' . socket_strerror(socket_last_error()) . "\n";
}
if (!socket_bind($serverSocket, $address, $port)) {
echo 'socket_bind() failed: reason: ' . socket_strerror(socket_last_error($serverSocket)) . "\n";
}
if (!socket_listen($serverSocket)) {
echo 'socket_listen() failed: reason: ' . socket_strerror(socket_last_error($serverSocket)) . "\n";
}
do {
$clientSocket = socket_accept($serverSocket);
if ($clientSocket === false) {
echo 'socket_accept() failed: reason: ' . socket_strerror(socket_last_error($serverSocket)) . "\n";
break;
}
$pid = pcntl_fork();
if ($pid === -1) {
die('Can\'t fork process');
}
if ($pid) {
echo "Someone connected $pid \n";
pcntl_waitpid($pid, $status, WNOHANG);
echo "Someone disconnected \n";
} else {
/* Send instructions. */
$msg = "\nWelcome to the brackets analyzer!. \n" .
"Enter a string to analyze. \n" .
"To quit, type 'quit'\n";
socket_write($clientSocket, $msg, strlen($msg));
do {
$buf = socket_read($clientSocket, 2048, PHP_NORMAL_READ);
if ($buf === false) {
echo 'socket_read() failed: reason: ' . socket_strerror(socket_last_error($clientSocket)) . "\n";
break;
}
if (!$buf = trim($buf)) {
continue;
}
if ($buf === 'quit') {
$msg = "Goodbye!\n";
socket_write($clientSocket, $msg, strlen($msg));
exit();
}
$talkback = "PHP: You said '$buf'.\n";
socket_write($clientSocket, $talkback, strlen($talkback));
} while (true);
}
socket_close($clientSocket);
} while (true);
socket_close($serverSocket);
UPD: Я пытался добавить обработчик SIGCHLD
позвонив по номеру pcntl_signal
(полный код приведен ниже).
Проблема в том, что, когда кто-то выходит из дочернего процесса, процесс завершается и становится процессом зомби, но следующее соединение с сервером немедленно удаляет все процессы зомби.
Я действительно не понимаю, как это работает.
Как добиться того, чтобы дочерний процесс правильно закрылся немедленно?
declare(ticks = 1);
set_time_limit(0);
/* Turn on implicit output flushing so we see what we're getting
* as it comes in. */
ob_implicit_flush();
declare(ticks = 1);
pcntl_signal(SIGCHLD, function () {
pcntl_waitpid(-1, $status);
echo "Someone disconnected \n";
});
$address = '192.168.0.100';
$port = 7888;
$serverSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($serverSocket=== false) {
echo 'socket_create() failed: reason: ' . socket_strerror(socket_last_error()) . "\n";
}
if (!socket_bind($serverSocket, $address, $port)) {
echo 'socket_bind() failed: reason: ' . socket_strerror(socket_last_error($serverSocket)) . "\n";
}
if (!socket_listen($serverSocket)) {
echo 'socket_listen() failed: reason: ' . socket_strerror(socket_last_error($serverSocket)) . "\n";
}
do {
$clientSocket = socket_accept($serverSocket);
if ($clientSocket === false) {
echo 'socket_accept() failed: reason: ' . socket_strerror(socket_last_error($serverSocket)) . "\n";
break;
}
$pid = pcntl_fork();
if ($pid === -1) {
die('Can\'t fork process');
}
if ($pid) {
echo "Someone connected $pid \n";
} else {
/* Send instructions. */
$msg = "\nWelcome to the brackets analyzer!. \n" .
"Enter a string to analyze. \n" .
"To quit, type 'quit'\n";
socket_write($clientSocket, $msg, strlen($msg));
do {
$buf = socket_read($clientSocket, 2048, PHP_NORMAL_READ);
if ($buf === false) {
echo 'socket_read() failed: reason: ' . socket_strerror(socket_last_error($clientSocket)) . "\n";
break;
}
if (!$buf = trim($buf)) {
continue;
}
if ($buf === 'quit') {
$msg = "Goodbye!\n";
socket_write($clientSocket, $msg, strlen($msg));
exit();
}
$talkback = "PHP: You said '$buf'.\n";
socket_write($clientSocket, $talkback, strlen($talkback));
} while (true);
}
socket_close($clientSocket);
} while (true);
socket_close($serverSocket);