1--TEST--
2Killing server should terminate all worker processes
3--ENV--
4PHP_CLI_SERVER_WORKERS=2
5--SKIPIF--
6<?php
7include "skipif.inc";
8if (!(str_contains(PHP_OS, 'Linux') || str_contains(PHP_OS, 'FreeBSD'))) {
9    die('skip PDEATHSIG is only supported on Linux and FreeBSD');
10}
11if (@file_exists('/.dockerenv')) die("skip Broken in Docker");
12?>
13--FILE--
14<?php
15
16function split_words(?string $lines): array {
17    return preg_split('(\s)', trim($lines ?? ''), flags: PREG_SPLIT_NO_EMPTY);
18}
19
20function find_workers_by_ppid(string $ppid) {
21    return split_words(shell_exec('pgrep -P ' . $ppid));
22}
23
24function find_workers_by_pids(array $pids) {
25    return split_words(shell_exec('ps -o pid= -p ' . join(',', $pids)));
26}
27
28include "php_cli_server.inc";
29$cliServerInfo = php_cli_server_start('');
30
31$master = proc_get_status($cliServerInfo->processHandle)['pid'];
32$workersBefore = find_workers_by_ppid($master);
33if (count($workersBefore) === 0) {
34    throw new \Exception('Could not find worker pids');
35}
36
37proc_terminate($cliServerInfo->processHandle, 9); // SIGKILL
38
39$try = 1;
40$max_tries = 20;
41while (true) {
42    $workersAfter = find_workers_by_pids($workersBefore);
43    if (count($workersAfter) === 0) {
44        break;
45    }
46    if ($try >= $max_tries) {
47        throw new \Exception('Workers were not properly terminated. Before: ' . join(', ', $workersBefore) . ', after: ' . join(', ', $workersAfter));
48    }
49    $try++;
50    usleep(100_000);
51}
52
53echo 'Done';
54?>
55--EXPECT--
56Done
57