Как сломать дочерний процесс таким образом, чтобы он не стал зомби-процессом? - PullRequest
0 голосов
/ 01 апреля 2019

Есть небольшой скрипт, который прослушивает порт.Когда кто-то подключен, процесс разветвляется.
Проблема в том, что когда дочерний процесс закрывается, он не закрывается правильно, а становится процессом зомби.

Также хочу добавить, что для меня важно, чтобы скрипт работал асинхронно и мог поддерживать несколько входящих соединений.

Как правильно завершить дочерние процессы в моем случае?
Ниже приведен код скрипта:

$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);
...