PHP 8.5.0 Alpha 1 available for testing

Voting

: two plus zero?
(Example: nine)

The Note You're Voting On

qu4qu426com123 at gmail dot com
2 years ago
Simple solution if you want to reading result from child process into the parent thread that based on socket.
Hope this can be of use to someone.

<?php
function fork_process(...$callbacks)
{
$callbackSocket = [];
$callbacks = array_filter($callbacks, function ($callback) {
return
$callback instanceof \Closure;
});
/* On Windows need to use AF_INET */
$domain = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' ? AF_INET : AF_UNIX);
$pids = [];
foreach (
$callbacks as $index => $callback) {
$setUpCallbackSocket = socket_create_pair($domain, SOCK_STREAM, 0, $callbackSocket[$index]);
if (!
$setUpCallbackSocket) {
throw new
\Exception(
"socket_create_pair failed. Reason: " . socket_strerror(socket_last_error()),
1
);
}
$pid = pcntl_fork();
if (
$pid == 0) {
try {
$returnValue = $callback();
// Declare $sendingData end of line , prevent socket_read hangs
$sendingData = serialize($returnValue) . "\0\r\n";
$bufferLength = mb_strlen($sendingData, '8bit');
// If not declare $bufferLength, it is silently truncated to the length of SO_SNDBUF
// @see https://www.php.net/manual/en/function.socket-write.php
// @see https://www.php.net/manual/en/function.socket-get-option.php
socket_write($callbackSocket[$index][0], $sendingData, $bufferLength);
socket_close($callbackSocket[$index][0]);
} finally {
// Explicity kill process, or else the resource shared with parent will be closed
posix_kill(getmypid(), SIGTERM);
exit();
}
} else {
$pids[$index] = $pid;
}
}
$results = [];
foreach (
$pids as $index => $pid) {
pcntl_waitpid($pid, $status);
$msg = "";
while (
$resp = socket_read($callbackSocket[$index][1], 102400)) {
$msg .= $resp;
// prevent socket_read hangs
if ($msg[-1] === "\n" && $msg[-2] === "\r" && $msg[-3] === "\0") {
break;
}
}
socket_close($callbackSocket[$index][1]);
$results[] = unserialize(trim($msg));
}
return
$results;
}

$time = microtime(true);
$resp = fork_process(
function () {
sleep(1);
return
'first';
},
function () {
sleep(2);
return
'second';
},
);
echo (
microtime(true) - $time);
// 2.0448851585388
echo implode(' ', $resp);
// first second
?>
Inspired by https://stackoverflow.com/questions/8707339/sharing-variables-between-child-processes-in-php

<< Back to user notes page

To Top