Commit 023ee4dc998 for php
commit 023ee4dc9983b036ccf889cd1cd70b0016716ef9
Author: Lazizbek Ergashev <lazerg2@gmail.com>
Date: Tue Sep 29 21:02:57 2026 +0500
Fix GH-23986: Clear the realpath cache in the child after pcntl_fork() (#23987)
diff --git a/NEWS b/NEWS
index 8eb6798b700..4ace934375f 100644
--- a/NEWS
+++ b/NEWS
@@ -94,6 +94,8 @@ PHP NEWS
the inclusive upper bound. (lacatoire)
. Fixed pcntl_setqos_class() requiring its optional $qos_class argument.
(lacatoire)
+ . Fixed bug GH-23986 (/proc/self paths resolve to the parent process after
+ pcntl_fork()). (Lazizbek Ergashev)
- PDO:
. Fixed PDOStatement::getColumnMeta() reading out of bounds for an invalid
diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c
index 34a67028263..1858ee6e4a7 100644
--- a/ext/pcntl/pcntl.c
+++ b/ext/pcntl/pcntl.c
@@ -29,6 +29,7 @@
#include "php.h"
#include "ext/standard/info.h"
+#include "ext/standard/php_filestat.h"
#include "php_signal.h"
#include "php_ticks.h"
#include "zend_exceptions.h"
@@ -294,6 +295,7 @@ PHP_FUNCTION(pcntl_fork)
}
} else if (id == 0) {
zend_max_execution_timer_init();
+ php_clear_stat_cache(true, NULL, 0);
}
RETURN_LONG((zend_long) id);
@@ -1573,6 +1575,7 @@ PHP_FUNCTION(pcntl_rfork)
}
} else if (pid == 0) {
zend_max_execution_timer_init();
+ php_clear_stat_cache(true, NULL, 0);
}
RETURN_LONG((zend_long) pid);
@@ -1618,6 +1621,7 @@ PHP_FUNCTION(pcntl_forkx)
}
} else if (pid == 0) {
zend_max_execution_timer_init();
+ php_clear_stat_cache(true, NULL, 0);
}
RETURN_LONG((zend_long) pid);
diff --git a/ext/pcntl/tests/gh23986.phpt b/ext/pcntl/tests/gh23986.phpt
new file mode 100644
index 00000000000..7b9976d5007
--- /dev/null
+++ b/ext/pcntl/tests/gh23986.phpt
@@ -0,0 +1,29 @@
+--TEST--
+GH-23986 (/proc/self paths resolve to the parent process after pcntl_fork())
+--EXTENSIONS--
+pcntl
+--SKIPIF--
+<?php
+if (!is_readable('/proc/self/stat')) die('skip /proc/self/stat not available');
+?>
+--FILE--
+<?php
+function proc_self_pid() {
+ return (int) explode(' ', file_get_contents('/proc/self/stat'))[0];
+}
+
+var_dump(proc_self_pid() === getmypid());
+$parent_inode = fileinode('/proc/self');
+
+$pid = pcntl_fork();
+if ($pid === 0) {
+ var_dump(fileinode('/proc/self') !== $parent_inode);
+ var_dump(proc_self_pid() === getmypid());
+ exit(0);
+}
+pcntl_waitpid($pid, $status);
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)