-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathphp_fork.txt
More file actions
executable file
·53 lines (44 loc) · 2.78 KB
/
php_fork.txt
File metadata and controls
executable file
·53 lines (44 loc) · 2.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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 = 50;
// Fork child processes
for ($i = 0; $i < $child_count; $i++) {
\e[36m# pcntl_fork() splits the script \e[1mat the point where it is called\e[0;36m. The two copies of the script know what they are
\e[36m# 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.\e[0m
$pid = pcntl_fork();
if ($pid == -1) {
die('Could not fork');
} elseif ($pid == 0) {
\e[36m# Child process: do all the Child things, send the results to the queue, then \e[1mexit\e[0m
$sleepTime = rand(1, 5);
sleep($sleepTime);
\e[36m# Send a message to the parent\e[0m
msg_send($queue, 1, "Child $i slept for $sleepTime seconds");
exit(0); \e[32;1m# <-- this mofo \e[4mNeeds Adding\e[24m if you're converting a regular loop to a forking one\e[0m
} else { \e[36m# optional..\e[0m
\e[36m# Parent process\e[0m
\e[36m# nothing needs doing here, the parent will wait for child messages later\e[0m
}
}
# 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. \e[38;5;208mipcs\e[0m will show you current message queues.
msg_remove_queue($queue);
# You might be tempted to use register_shutdown_function() for this (ChatGPT told me to!) but that will also fire as soon as
# the first child process exits, sooo.. don't.
# If all else fails, from the cli use \e[38;5;208mipcrm -q <msqid>\e[0m, where the \e[1mmsqid\e[0m shows up under the output of \e[38;5;208mipcs -q\e[0m.
# If that ALSO fails because \e[38;5;208mipcrm\e[0m doesn't exist, go back to PHP. Get the \e[1mkey\e[0m, not the msqid from ipcs -q:
$ php -r '$id = <key>; $q = msg_get_queue($id); msg_remove_queue($q);'
# no need to quote the key, it's an integer, just usually in hex notation which is more common in low-level system programming.
# 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