Description
After pcntl_fork(), a path under /proc/self that the parent already used resolves, in the child, to the parent's /proc/<pid>: the realpath cache kept the resolved symlink across the fork. The child reads the parent's process information.
<?php
$pid = fn() => (int) explode(' ', file_get_contents('/proc/self/stat'))[0];
echo "parent: ", $pid() === getmypid() ? "ok" : "wrong", "\n";
if (pcntl_fork() === 0) {
echo "child: /proc/self/stat says ", $pid(), ", getmypid() ", getmypid(), "\n";
exit(0);
}
pcntl_wait($status);
Resulted in this output:
parent: ok
child: /proc/self/stat says 3248499, getmypid() 3248500
But I expected this output instead:
parent: ok
child: /proc/self/stat says 3248500, getmypid() 3248500
clearstatcache(true) in the child works around it. The same happens with scandir('/proc/self/task') and the like, on NTS and ZTS builds. /proc/self (and /proc/thread-self) are symlinks whose target depends on the process reading them, so they shouldn't be cached, or the realpath cache could be cleared in the child of pcntl_fork().
PHP Version
PHP 8.5.11 (cli) (NTS); also 8.4.26 (cli) (ZTS)
Operating System
Ubuntu 24.04 (x86_64); Alpine 3.22 (Docker)
Description
After
pcntl_fork(), a path under/proc/selfthat the parent already used resolves, in the child, to the parent's/proc/<pid>: the realpath cache kept the resolved symlink across the fork. The child reads the parent's process information.Resulted in this output:
But I expected this output instead:
clearstatcache(true)in the child works around it. The same happens withscandir('/proc/self/task')and the like, on NTS and ZTS builds./proc/self(and/proc/thread-self) are symlinks whose target depends on the process reading them, so they shouldn't be cached, or the realpath cache could be cleared in the child ofpcntl_fork().PHP Version
Operating System
Ubuntu 24.04 (x86_64); Alpine 3.22 (Docker)