SSE terminate the script & proc_open leaves child's running in background
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 40.4k
- Forks
- 8.1k
- Avg merge
- 2d 13h
- Merged PRs (30d)
- 96
Description
Description
This code is simply a combination of Mozilla Server-Sent Events Example and PHP proc_open() Example, which make the browser receive the output of a command in real-time.
The first issue is proc_terminate() leaves children running, which is already open since 2006, but people suggested some workarounds (workarounds 1, 2, 4).
The second issue which is why I'm open this, is the PHP script get killed as soon as the SSE connection get closed, which mean kill_process($process) never reached, while in PHP 5.6 the script still alive and terminate normally. I fix it by register_shutdown_function() (workarounds 3).
<?php
// --------------------------------------------
set_time_limit(0);
ini_set('auto_detect_line_endings', 1);
ini_set('max_execution_time', '0');
date_default_timezone_set("America/Halifax");
ob_end_clean();
gc_enable();
header("Content-Type: text/event-stream");
header("Cache-Control: no-store");
header('Access-Control-Allow-Credentials: true');
header("Access-Control-Allow-Origin: *");
header('Access-Control-Expose-Headers: X-Events');
// -------------------------------------------
$process;
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
$env = '/home';
$pipes;
$process;
// -------------------------------------------
function kill_process() {
global $process;
$status = proc_get_status($process);
if($status['running'] == true) {
// Close all pipes that are still open
fclose($pipes[1]); //stdout
fclose($pipes[2]); //stderr
// Get the parent pid of the process we want to kill
$ppid = $status['pid'];
// Use ps to get all the children of this process, and kill them
$pids = preg_split('/\s+/', `ps -o pid --no-heading --ppid $ppid`);
foreach($pids as $pid) {
if(is_numeric($pid)) {
posix_kill($pid, 9); // SIGKILL
}
}
}
// Workaround 1
posix_kill($ppid, 9);
// Close The Process
proc_close($process);
// Workaround 2
proc_terminate($process);
}
function SendEventToBrowser($event, $msg) {
echo ("event: $msg\n".PHP_EOL);
echo ("data: $msg\n".PHP_EOL);
while (ob_get_level() > 0)
ob_end_flush();
flush();
}
function SendToBrowser($msg) {
echo ("data: $msg\n".PHP_EOL);
while (ob_get_level() > 0)
ob_end_flush();
flush();
}
// ---------------------------------------------
// Workaround 3
register_shutdown_function('kill_process');
// Workaround 4 (exec)
$process = proc_open("exec /bin/bash /home/MyScript.sh", $descriptorspec, $pipes, $env, array());
if(is_resource($process)) {
SendToBrowser('Shell Script Started');
while ($s = fgets($pipes[1])) {
SendToBrowser($s);
// break the loop if the client
// aborted the connection
if (connection_aborted()){
break;
}
}
kill_process($process); // Never Reached
}
SendToBrowser('Shell Script Closed');
?>
PHP Version
PHP 7.4.3 (cli) (built: Mar 2 2022 15:36:52) ( NTS )
Operating System
Ubuntu 20.04.4 LTS
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
No repository files or tests are identified. Start by reproducing the SSE disconnect with PHP 7.4.3 on Ubuntu 20.04, then read the proc_open(), proc_terminate(), and register_shutdown_function() entry points and the linked child-process bug. Done means the child process is not left running after the connection closes, with regression coverage for the reported lifecycle.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash, php
- Domain
- backend, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100