-
Notifications
You must be signed in to change notification settings - Fork 8k
opcache_is_script_cached_in_file_cache(string $filename) #16979
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 20 commits
200193b
798a07d
824e638
30641d6
283844e
8cc7293
fd93557
7e23285
906b92d
1cdf3fa
f620d9c
6df1562
e282578
17edbe6
cd0177f
7cff70a
59a4ecc
b3b9501
d1b74e9
1b8311b
3e573f3
9346db9
f9c05a1
d750ae0
fbb4194
e36a92d
4c99bd0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?php | ||
|
||
$a = 4+5; | ||
|
||
echo $a . "\n"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?php | ||
|
||
$a = 3+5; | ||
|
||
echo $a . "\n"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
--TEST-- | ||
GH-16551: Behavior with opcache.file_cache_only=1 | ||
--SKIPIF-- | ||
<?php | ||
if (!extension_loaded('Zend OPcache')) die('skip Zend OPcache extension not available'); | ||
|
||
|
||
// Ensure the cache directory exists BEFORE OPcache needs it | ||
$cacheDir = __DIR__ . '/gh16551_fileonly_cache'; | ||
if (!is_dir($cacheDir)) { | ||
@mkdir($cacheDir, 0777, true); | ||
} | ||
// Check if mkdir failed potentially due to permissions | ||
if (!is_dir($cacheDir) || !is_writable($cacheDir)) { | ||
die('skip Could not create or write to cache directory: ' . $cacheDir); | ||
} | ||
?> | ||
--INI-- | ||
opcache.enable=1 | ||
opcache.enable_cli=1 | ||
opcache.jit=disable | ||
opcache.jit_buffer_size=0 | ||
opcache.file_cache="{PWD}/gh16551_fileonly_cache" | ||
opcache.file_cache_only=1 | ||
opcache.validate_timestamps=1 | ||
--EXTENSIONS-- | ||
opcache | ||
--FILE-- | ||
<?php | ||
$file = __DIR__ . '/gh16551_998.inc'; | ||
$uncached_file = __DIR__ . '/gh16551_999.inc'; | ||
$cacheDir = __DIR__ . '/gh16551_fileonly_cache'; | ||
|
||
echo "Initial state (file_cache_only mode):\n"; | ||
// SHM is always false, File Cache might be true in Pass 2 | ||
var_dump(opcache_is_script_cached($file)); | ||
var_dump(opcache_is_script_cached_in_file_cache($file)); | ||
|
||
echo "\nAttempting opcache_compile_file():\n"; | ||
opcache_compile_file($file); | ||
|
||
echo "\nState after compile attempt:\n"; | ||
// SHM remains false, File Cache becomes true | ||
var_dump(opcache_is_script_cached($file)); | ||
var_dump(opcache_is_script_cached_in_file_cache($file)); | ||
|
||
// Check file existence via glob | ||
echo "\nChecking file system for compiled file:\n"; | ||
if (substr(PHP_OS, 0, 3) === 'WIN') { | ||
$sanitizedDir = str_replace(':', '', __DIR__); | ||
$pattern = $cacheDir . DIRECTORY_SEPARATOR . '*' . DIRECTORY_SEPARATOR . '*' . DIRECTORY_SEPARATOR . $sanitizedDir . DIRECTORY_SEPARATOR . 'gh16551_998.inc.bin'; | ||
} else { | ||
$pattern = $cacheDir . DIRECTORY_SEPARATOR . '*' . DIRECTORY_SEPARATOR . __DIR__ . DIRECTORY_SEPARATOR . 'gh16551_998.inc.bin'; | ||
} | ||
$found = glob($pattern); | ||
var_dump(count($found) > 0); // Expect true after compile | ||
|
||
echo "\nAttempting require:\n"; | ||
require $file; // Outputs 9, should execute from file cache | ||
|
||
echo "\nState after require:\n"; | ||
// State remains unchanged | ||
var_dump(opcache_is_script_cached($file)); | ||
var_dump(opcache_is_script_cached_in_file_cache($file)); | ||
|
||
echo "\nChecking uncached file initial state:\n"; | ||
// SHM false, File Cache might be true in Pass 2 for this file too | ||
var_dump(opcache_is_script_cached($uncached_file)); | ||
var_dump(opcache_is_script_cached_in_file_cache($uncached_file)); | ||
|
||
echo "\nRequiring uncached file:\n"; | ||
require $uncached_file; // Outputs 8, should compile to file cache now | ||
|
||
echo "\nState after requiring uncached file:\n"; | ||
// SHM remains false, File cache becomes true for this file | ||
var_dump(opcache_is_script_cached($uncached_file)); | ||
var_dump(opcache_is_script_cached_in_file_cache($uncached_file)); | ||
|
||
?> | ||
--CLEAN-- | ||
<?php | ||
$baseCacheDir = __DIR__ . '/gh16551_fileonly_cache'; | ||
|
||
function removeDirRecursive($dir) { | ||
if (!is_dir($dir)) return; | ||
try { | ||
$iterator = new RecursiveIteratorIterator( | ||
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS), | ||
RecursiveIteratorIterator::CHILD_FIRST | ||
); | ||
foreach ($iterator as $fileinfo) { | ||
if ($fileinfo->isDir()) { | ||
@rmdir($fileinfo->getRealPath()); | ||
} else { | ||
@unlink($fileinfo->getRealPath()); | ||
} | ||
} | ||
@rmdir($dir); | ||
} catch (UnexpectedValueException $e) { @rmdir($dir); } catch (Exception $e) { @rmdir($dir); } | ||
} | ||
|
||
|
||
removeDirRecursive($baseCacheDir); | ||
?> | ||
--EXPECTF-- | ||
Initial state (file_cache_only mode): | ||
bool(false) | ||
bool(%s) | ||
|
||
|
||
Attempting opcache_compile_file(): | ||
|
||
State after compile attempt: | ||
bool(false) | ||
bool(true) | ||
|
||
Checking file system for compiled file: | ||
bool(true) | ||
|
||
Attempting require: | ||
9 | ||
|
||
State after require: | ||
bool(false) | ||
bool(true) | ||
|
||
Checking uncached file initial state: | ||
bool(false) | ||
bool(%s) | ||
|
||
Requiring uncached file: | ||
8 | ||
|
||
State after requiring uncached file: | ||
bool(false) | ||
bool(true) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
--TEST-- | ||
GH-16551: Verify opcache_invalidate fails or is ineffective when opcache.file_cache_only=1 | ||
--SKIPIF-- | ||
<?php | ||
if (!extension_loaded('Zend OPcache')) die('skip Zend OPcache extension not available'); | ||
if (substr(PHP_OS, 0, 3) == 'WIN') die('skip Test relies on shell_exec and specific helper script pathing, skipping on Windows'); | ||
$php_binary = getenv('TEST_PHP_EXECUTABLE'); | ||
if (!$php_binary) die('skip TEST_PHP_EXECUTABLE environment variable not set'); | ||
if (!is_executable($php_binary)) die("skip $php_binary is not executable"); | ||
|
||
// Ensure the cache directory exists BEFORE OPcache needs it | ||
$cacheDir = __DIR__ . '/gh16551_invalidate_fco_cache'; | ||
if (!is_dir($cacheDir)) { | ||
@mkdir($cacheDir, 0777, true); | ||
} | ||
// Check if mkdir failed potentially due to permissions | ||
if (!is_dir($cacheDir) || !is_writable($cacheDir)) { | ||
die('skip Could not create or write to cache directory: ' . $cacheDir); | ||
} | ||
?> | ||
--INI-- | ||
; Main test runs with file_cache_only=1 | ||
opcache.enable=1 | ||
opcache.enable_cli=1 | ||
opcache.jit=disable | ||
opcache.jit_buffer_size=0 | ||
opcache.file_cache="{PWD}/gh16551_invalidate_fco_cache" | ||
opcache.file_cache_only=1 | ||
opcache.validate_timestamps=0 | ||
--EXTENSIONS-- | ||
opcache | ||
--FILE-- | ||
<?php | ||
$phpBinary = getenv('TEST_PHP_EXECUTABLE'); | ||
$helperScript = __DIR__ . '/gh16551_populate_cache_helper.inc'; | ||
$fileToCache = __DIR__ . '/gh16551_998.inc'; | ||
$cacheDir = __DIR__ . '/gh16551_invalidate_fco_cache'; | ||
$helperOutputFile = $cacheDir . '/helper_output.txt'; | ||
|
||
// 1. Populate cache using helper (runs WITHOUT file_cache_only=1) | ||
$opcache_extension = (PHP_SHLIB_SUFFIX === 'dll') ? 'php_opcache.dll' : 'opcache.so'; | ||
$cmd = escapeshellarg($phpBinary) . ' ' . | ||
'-n ' . // <-- Tell PHP *not* to load any php.ini files | ||
'-d zend_extension=' . escapeshellarg($opcache_extension) . ' '. // <-- Explicitly load OPcache | ||
'-d opcache.enable=1 -d opcache.enable_cli=1 ' . | ||
'-d opcache.file_cache=' . escapeshellarg($cacheDir) . ' ' . | ||
'-d opcache.file_cache_only=0 ' . // <-- Helper runs normally | ||
'-d opcache.validate_timestamps=1 ' . | ||
'-d opcache.jit_buffer_size=0 ' . // Ensure helper doesn't try JIT | ||
escapeshellarg($helperScript) . ' ' . | ||
escapeshellarg($fileToCache) . ' ' . | ||
escapeshellarg($cacheDir) . ' ' . // Pass path for verification/output | ||
escapeshellarg($helperOutputFile); | ||
|
||
|
||
echo "Running helper script to populate cache...\n"; | ||
$helperResult = shell_exec($cmd); // Execute the command | ||
|
||
// 3. Check if helper script succeeded via output file | ||
if (!file_exists($helperOutputFile) || trim(file_get_contents($helperOutputFile)) !== 'SUCCESS') { | ||
echo "Helper script failed:\n"; | ||
|
||
if (file_exists($helperOutputFile)) { | ||
readfile($helperOutputFile); // Show helper error message | ||
} else { | ||
echo "Helper output file '$helperOutputFile' not found."; | ||
} | ||
echo "\nShell Exec Output: " . $helperResult; | ||
exit(1); // Abort test | ||
} | ||
echo "Helper script successful.\n"; | ||
|
||
// 2. Verify cache exists in main process (running file_cache_only=1) | ||
echo "\nVerifying initial state (file_cache_only=1, cache populated):\n"; | ||
var_dump(opcache_is_script_cached($fileToCache)); // Should be false (SHM not used) | ||
var_dump(opcache_is_script_cached_in_file_cache($fileToCache)); // Should be true | ||
|
||
// 3. Attempt to invalidate (should fail or do nothing due to file_cache_only=1) | ||
echo "\nAttempting opcache_invalidate() with file_cache_only=1:\n"; | ||
$invalidate_result = opcache_invalidate($fileToCache, true); // force=true | ||
var_dump($invalidate_result); // Expect bool(false) as the function exits early | ||
|
||
// 4. Verify cache state *after* invalidate attempt (should be unchanged) | ||
echo "\nVerifying state after invalidate attempt:\n"; | ||
var_dump(opcache_is_script_cached($fileToCache)); // Still false | ||
var_dump(opcache_is_script_cached_in_file_cache($fileToCache)); // Should STILL be true | ||
|
||
?> | ||
--CLEAN-- | ||
<?php | ||
$baseCacheDir = __DIR__ . '/gh16551_invalidate_fco_cache'; | ||
|
||
function removeDirRecursive($dir) { | ||
if (!is_dir($dir)) return; | ||
try { | ||
$iterator = new RecursiveIteratorIterator( | ||
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS), | ||
RecursiveIteratorIterator::CHILD_FIRST | ||
); | ||
foreach ($iterator as $fileinfo) { | ||
if ($fileinfo->isDir()) { | ||
@rmdir($fileinfo->getRealPath()); | ||
} else { | ||
@unlink($fileinfo->getRealPath()); | ||
} | ||
} | ||
@rmdir($dir); | ||
} catch (UnexpectedValueException $e) { @rmdir($dir); } catch (Exception $e) { @rmdir($dir); } | ||
} | ||
|
||
removeDirRecursive($baseCacheDir); | ||
?> | ||
--EXPECTF-- | ||
Running helper script to populate cache... | ||
Helper script successful. | ||
|
||
Verifying initial state (file_cache_only=1, cache populated): | ||
bool(false) | ||
bool(true) | ||
|
||
Attempting opcache_invalidate() with file_cache_only=1: | ||
bool(false) | ||
|
||
Verifying state after invalidate attempt: | ||
bool(false) | ||
bool(true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this called 998? Also, why does it output 9, while 999 outputs 8. :D