Skip to content

Instantly share code, notes, and snippets.

@xputerax
Created September 18, 2024 23:07
Show Gist options
  • Save xputerax/1e52cc5454dfd781d36889ce41499779 to your computer and use it in GitHub Desktop.
Save xputerax/1e52cc5454dfd781d36889ce41499779 to your computer and use it in GitHub Desktop.
PHP IPC demo using pcntl_fork
<?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