|
| 1 | +--TEST-- |
| 2 | +opcache_compile_file() should early-bind parentless classes |
| 3 | +--EXTENSIONS-- |
| 4 | +opcache |
| 5 | +--INI-- |
| 6 | +opcache.enable=1 |
| 7 | +opcache.enable_cli=1 |
| 8 | +--FILE-- |
| 9 | +<?php |
| 10 | +$cacheDir = __DIR__ . '/opcache_early_bind_no_parent_cache'; |
| 11 | +@mkdir($cacheDir, 0777, true); |
| 12 | + |
| 13 | +$incFile = __DIR__ . '/opcache_compile_file_early_bind_no_parent.inc'; |
| 14 | +$php = PHP_BINARY; |
| 15 | + |
| 16 | +/* Detect opcache extension path for subprocess invocations. |
| 17 | + * Always search for the shared module since subprocesses won't inherit |
| 18 | + * the parent's zend_extension settings from run-tests.php. */ |
| 19 | +$opcacheExt = ''; |
| 20 | +$candidates = [ |
| 21 | + ini_get('extension_dir') . '/opcache.so', |
| 22 | + ini_get('extension_dir') . '/opcache', |
| 23 | + dirname(PHP_BINARY, 3) . '/modules/opcache.so', |
| 24 | + dirname(PHP_BINARY, 2) . '/modules/opcache.so', |
| 25 | +]; |
| 26 | +foreach ($candidates as $path) { |
| 27 | + $real = realpath($path); |
| 28 | + if ($real !== false) { |
| 29 | + $opcacheExt = '-d zend_extension=' . escapeshellarg($real); |
| 30 | + break; |
| 31 | + } |
| 32 | +} |
| 33 | + |
| 34 | +$opcacheArgs = implode(' ', array_filter([ |
| 35 | + '-n', |
| 36 | + $opcacheExt, |
| 37 | + '-d opcache.enable=1', |
| 38 | + '-d opcache.enable_cli=1', |
| 39 | + '-d opcache.file_cache=' . escapeshellarg($cacheDir), |
| 40 | + '-d opcache.file_cache_only=1', |
| 41 | + '-d opcache.file_update_protection=0', |
| 42 | + '-d opcache.jit=disable', |
| 43 | +])); |
| 44 | + |
| 45 | +/* First invocation: compile the file into file cache */ |
| 46 | +$cmd = "$php $opcacheArgs -r " . escapeshellarg( |
| 47 | + 'opcache_compile_file(' . var_export($incFile, true) . '); echo "compiled\n";' |
| 48 | +); |
| 49 | +echo shell_exec($cmd); |
| 50 | + |
| 51 | +/* Second invocation: include the file from file cache. |
| 52 | + * The parentless class must be early-bound for NoParentClass::VALUE |
| 53 | + * to be accessible before the ZEND_DECLARE_CLASS_DELAYED opcode runs. */ |
| 54 | +$cmd = "$php $opcacheArgs -r " . escapeshellarg( |
| 55 | + 'include ' . var_export($incFile, true) . '; echo "included\n";' |
| 56 | +); |
| 57 | +echo shell_exec($cmd); |
| 58 | +?> |
| 59 | +--CLEAN-- |
| 60 | +<?php |
| 61 | +function removeDirRecursive($dir) { |
| 62 | + if (!is_dir($dir)) return; |
| 63 | + $iterator = new RecursiveIteratorIterator( |
| 64 | + new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS), |
| 65 | + RecursiveIteratorIterator::CHILD_FIRST |
| 66 | + ); |
| 67 | + foreach ($iterator as $fileinfo) { |
| 68 | + if ($fileinfo->isDir()) { |
| 69 | + @rmdir($fileinfo->getRealPath()); |
| 70 | + } else { |
| 71 | + @unlink($fileinfo->getRealPath()); |
| 72 | + } |
| 73 | + } |
| 74 | + @rmdir($dir); |
| 75 | +} |
| 76 | +removeDirRecursive(__DIR__ . '/opcache_early_bind_no_parent_cache'); |
| 77 | +?> |
| 78 | +--EXPECT-- |
| 79 | +compiled |
| 80 | +hello |
| 81 | +included |
0 commit comments