Closed withinboredom closed 1 year ago
Unfortunately, this is exactly what it's designed to do. The issue is that PHP doesn't open FDs with the close on exec option, so any child process will inherit the file descriptors. We shutdown the sockets so they don't stay open in case any child process is started while the socket was open.
The issue is that PHP doesn't open FDs with the close on exec option, so any child process will inherit the file descriptors
This is pretty much how things are done in Linux. In fact, after a fork()
in C, you usually do something like this and manually close them all yourself; but generally, you don't want to break them in the parent.
Alternatively, call pcntl_unshare(1024)
in the child to disassociate the FD table with the parent. Granted, it's PHP so a lot happens between fork
and your call to unshare
... so YMMV.
Or, if you're lucky enough to be on BSD, there's pcntl_rfork
which allows you to fork without FDs being copied.
This should work IMHO, fwiw:
$pid = pcntl_fork();
if($pid === 0) {
foreach (EventLoop::getIdentifiers() as $identifier) {
EventLoop::cancel($identifier);
}
// clean process?
}
But now if any destructors get called in a child, for any reason (such as when the child dies), the entire program crashes and/or corrupts things in databases (depending on what gets destructed and in what order).
For the record, this was simply resolved by using the ZTS version of PHP.
When file descriptors are shared between processes or threads,
stream_socket_shutdown
will close the file descriptor for ALL threads/processes (took me forever to figure out what was going on) and cause broken pipes.