Created
October 31, 2023 12:00
-
-
Save mspreij/4c571ab93123520262ac3b8c5c0e0241 to your computer and use it in GitHub Desktop.
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
Example script that uses pcntl_fork() to fork itself a few dozen times, and System V IPC functions to create a message queue, | |
let the child processes send data to it and the parent process read and display it. | |
#!/usr/bin/env php | |
<?php | |
// Create or attach to a message queue | |
$queue = msg_get_queue(ftok(__FILE__, 'a'), 0600); # set permissions so that only the owner can read/write to this queue | |
# ftok() creates a message queue key based on the file's inode and a single character project identifier. The latter lets | |
# one create several queues all based on/in the same file. | |
$child_count = 3; | |
$records = query($sql....); | |
// Fork child processes | |
for ($i = 0; $i < $child_count; $i++) { | |
# pcntl_fork() splits the script at the point where it is called. The two copies of the script know what they are | |
# based on the value of $pid: 0 for the child, positive int for the parent (it will be the child's PID) or -1 for failure. | |
$pid = pcntl_fork(); | |
if ($pid == -1) { | |
die('Could not fork'); | |
} elseif ($pid) { | |
# Parent process | |
// Do nothing, will wait for child messages later | |
} else { | |
# Child process: do all the Child things, send the results to the queue, then exit | |
$process_records = array_slice($records, $i*10, 10); | |
# process $process_records here.. | |
# Send a message to the parent | |
msg_send($queue, 1, "Child $i done with job, result: ..."); | |
exit(0); | |
} | |
} | |
# Parent process waits to receive messages from all child processes | |
for ($i = 0; $i < $child_count; $i++) { | |
msg_receive($queue, 0, $msgType, 1024, $message, true); | |
echo "Received message: $message\n"; | |
} | |
# Destroy the message queue, otherwise it hangs around in memory. ipcs will show you current message queues. | |
msg_remove_queue($queue); | |
# You might be tempted to use register_shutdown_function() for this but that will also fire as soon as the first child | |
# process exits, sooo.. don't. | |
# If all else fails, from the cli use ipcrm -q <msqid>, where the msqid shows up under the output of ipcs. | |
# Other considerations: | |
# - make sure the child process Always exits, and always sends something to the queue before doing so, wrapping it in a try/catch | |
# should work | |
# - counting $children++ inside the child process does not work, this variable will not be incremented in the parent process. | |
# you can increment it in the parent branch of the $pid fork. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment