Skip to content

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

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
200193b
opcache_is_script_cached: file_cache option
iamacarpet Nov 28, 2024
798a07d
opcache_is_script_cached: file_cache: test
iamacarpet Nov 28, 2024
824e638
fix when file_cache_read_only
iamacarpet Nov 28, 2024
30641d6
remove file_cache_only
iamacarpet Nov 28, 2024
283844e
switch to zend_file_cache_script_validate(...)
iamacarpet Nov 29, 2024
8cc7293
fix build
iamacarpet Dec 2, 2024
fd93557
switch to opcache_is_script_cached_in_file_cache(...)
iamacarpet Dec 2, 2024
7e23285
remove double close(fd)
iamacarpet Dec 2, 2024
906b92d
zend_file_cache_open with struct
iamacarpet Dec 2, 2024
1cdf3fa
fix build
iamacarpet Dec 2, 2024
f620d9c
Unit Tests for GH-16551
iamacarpet Dec 3, 2024
6df1562
fix for file_cache_only
iamacarpet Dec 3, 2024
e282578
probe ARM test failure
iamacarpet Dec 4, 2024
17edbe6
remove unnecessary tests
iamacarpet Dec 4, 2024
cd0177f
Merge remote-tracking branch 'origin/master' into opcache/opcache_is_…
iamacarpet Feb 3, 2025
7cff70a
switch to validate_only method
iamacarpet Feb 3, 2025
59a4ecc
Merge remote-tracking branch 'origin/master' into opcache/opcache_is_…
iamacarpet Feb 20, 2025
b3b9501
zend_file_cache_script_load_ex
iamacarpet Feb 20, 2025
d1b74e9
Merge remote-tracking branch 'origin/master' into opcache/opcache_is_…
iamacarpet Apr 24, 2025
1b8311b
improve unit tests
iamacarpet Apr 24, 2025
3e573f3
Merge remote-tracking branch 'origin/master' into opcache/opcache_is_…
iamacarpet Jul 11, 2025
9346db9
reduce whitespace
iamacarpet Jul 11, 2025
f9c05a1
simplify tests & isolate to current change
iamacarpet Jul 11, 2025
d750ae0
Merge branch 'opcache/opcache_is_script_cached_file' of https://githu…
iamacarpet Jul 11, 2025
fbb4194
fix local test run
iamacarpet Jul 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ext/opcache/opcache.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ function opcache_jit_blacklist(Closure $closure): void {}
function opcache_get_configuration(): array|false {}

function opcache_is_script_cached(string $filename): bool {}

function opcache_is_script_cached_in_file_cache(string $filename): bool {}
6 changes: 5 additions & 1 deletion ext/opcache/opcache_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions ext/opcache/tests/cleanup_helper.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

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); }
}
45 changes: 45 additions & 0 deletions ext/opcache/tests/gh16979_check_file_cache_function.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
--TEST--
GH-16979: Test opcache_is_script_cached_in_file_cache function
--SKIPIF--
<?php
// Ensure the cache directory exists BEFORE OPcache needs it
$cacheDir = __DIR__ . '/gh16979_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.file_cache="{PWD}/gh16979_cache"
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php

opcache_compile_file(__FILE__);

var_dump(opcache_is_script_cached_in_file_cache(__FILE__));

opcache_invalidate(__FILE__, true); // force=true

var_dump(opcache_is_script_cached_in_file_cache(__FILE__));

?>
--CLEAN--
<?php
require __DIR__ . '/cleanup_helper.inc';

$cacheDir = __DIR__ . '/gh16979_cache';

removeDirRecursive($cacheDir);
?>
--EXPECTF--
bool(true)
bool(false)
44 changes: 44 additions & 0 deletions ext/opcache/zend_accelerator_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@
#include <time.h>

#include "php.h"
#include "zend.h"
#include "ZendAccelerator.h"
#include "zend_API.h"
#include "zend_closures.h"
#include "zend_shared_alloc.h"
#include "zend_accelerator_blacklist.h"
#include "zend_file_cache.h"
#include "php_ini.h"
#include "SAPI.h"
#include "zend_virtual_cwd.h"
Expand Down Expand Up @@ -364,6 +366,23 @@ static int filename_is_in_cache(zend_string *filename)
return 0;
}

static int filename_is_in_file_cache(zend_string *filename)
{
zend_string *realpath = zend_resolve_path(filename);
if (!realpath) {
return 0;
}

zend_file_handle handle;
zend_stream_init_filename_ex(&handle, filename);
handle.opened_path = realpath;

zend_persistent_script *result = zend_file_cache_script_load_ex(&handle, true);
zend_destroy_file_handle(&handle);

return result != NULL;
}

static int accel_file_in_cache(INTERNAL_FUNCTION_PARAMETERS)
{
if (ZEND_NUM_ARGS() == 1) {
Expand Down Expand Up @@ -999,3 +1018,28 @@ ZEND_FUNCTION(opcache_is_script_cached)

RETURN_BOOL(filename_is_in_cache(script_name));
}

/* {{{ Return true if the script is cached in OPCache file cache, false if it is not cached or if OPCache is not running. */
ZEND_FUNCTION(opcache_is_script_cached_in_file_cache)
{
zend_string *script_name;

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_STR(script_name)
ZEND_PARSE_PARAMETERS_END();

if (!validate_api_restriction()) {
RETURN_FALSE;
}

// account for accelerator_enabled = false when file_cache_only = true
if (!(ZCG(accelerator_enabled) || ZCG(accel_directives).file_cache_only)) {
RETURN_FALSE;
}

if (!ZCG(accel_directives).file_cache) {
RETURN_FALSE;
}

RETURN_BOOL(filename_is_in_file_cache(script_name));
}
17 changes: 17 additions & 0 deletions ext/opcache/zend_file_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1871,7 +1871,14 @@ static void zend_file_cache_unserialize(zend_persistent_script *script,
zend_file_cache_unserialize_early_bindings(script, buf);
}

static zend_persistent_script file_cache_validate_success_script;

zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handle)
{
return zend_file_cache_script_load_ex(file_handle, false);
}

zend_persistent_script *zend_file_cache_script_load_ex(zend_file_handle *file_handle, bool validate_only)
{
zend_string *full_path = file_handle->opened_path;
int fd;
Expand Down Expand Up @@ -1948,6 +1955,16 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl
return NULL;
}

/* return here if validating */
if (validate_only) {
if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
}
close(fd);
efree(filename);
return &file_cache_validate_success_script;
}

checkpoint = zend_arena_checkpoint(CG(arena));
#if defined(__AVX__) || defined(__SSE2__)
/* Align to 64-byte boundary */
Expand Down
1 change: 1 addition & 0 deletions ext/opcache/zend_file_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

int zend_file_cache_script_store(zend_persistent_script *script, bool in_shm);
zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handle);
zend_persistent_script *zend_file_cache_script_load_ex(zend_file_handle *file_handle, bool validate_only);
void zend_file_cache_invalidate(zend_string *full_path);

#endif /* ZEND_FILE_CACHE_H */