Created
September 18, 2024 23:07
-
-
Save xputerax/1e52cc5454dfd781d36889ce41499779 to your computer and use it in GitHub Desktop.
PHP IPC demo using pcntl_fork
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
const SHM_KEY = 0x1337; | |
function printfln($str, ...$args) { | |
printf($str . "\n", ...$args); | |
} | |
function sprintfln($str, $args) { | |
return sprintf($str . "\n", ...$args); | |
} | |
function signal_handler($errno) { | |
global $child_pid; | |
switch ($errno) { | |
case SIGTERM: | |
printfln("SIGTERM"); | |
break; | |
case SIGINT: | |
printfln("SIGINT"); | |
break; | |
default: | |
printfln("signal %d received\n", $errno); | |
} | |
// parent process received the signal | |
if ($child_pid > 0) { | |
printf("Killing child process (PID %d)\n", $child_pid); | |
// not sure if the child process will ever receive this | |
// because the terminal output still shows SIGINT | |
// regardless of whether posix_kill is called or not | |
posix_kill($child_pid, SIGTERM); | |
pcntl_wait($status); // Wait for the child to exit | |
printf("Child process exited\n"); | |
} | |
die(); | |
} | |
pcntl_signal(SIGTERM, 'signal_handler'); | |
pcntl_signal(SIGINT, 'signal_handler'); | |
$mem = shm_attach(SHM_KEY, 1024); | |
if ($mem === false) { | |
die("failed to create shared memory area"); | |
} | |
$child_pid = pcntl_fork(); | |
if ($child_pid < 0) { | |
$errcode = pcntl_get_last_error(); | |
$errmsg = pcntl_strerror($errcode); | |
die(sprintfln("failed to fork (%d): %s", $errcode, $errmsg)); | |
} else if ($child_pid) { // in parent | |
printfln("parent process started"); | |
printfln("child pid: %d", $child_pid); | |
$i = 0; | |
while (true) { | |
sleep(3); // simulate some work | |
shm_put_var($mem, 1, "some data " . $i); | |
$i++; | |
pcntl_signal_dispatch(); | |
} | |
// unreachable | |
printfln("parent process finished"); | |
} else { // in child process | |
printfln("child process started"); | |
while (true) { | |
printfln("waiting for data"); | |
while (shm_has_var($mem, 1) === false) {} | |
printfln("received data"); | |
$val = shm_get_var($mem, 1); | |
var_dump($val); | |
$ret = shm_remove_var($mem, 1); | |
if ($ret === true) { | |
printfln("key removed"); | |
} else { | |
printfln("failed to remove key"); | |
} | |
pcntl_signal_dispatch(); | |
} | |
printfln("child process finished"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment