|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2010-11-04 00:56 UTC] pierre at archlinux dot de
Description:
------------
I am using PHP 5.3.3 (cannot be chosen in the bug tracker menu btw.) and APC 3.1.5 on Arch Linux x86_64.
My local APC config is:
apc.shm_size=128M
apc.stat=0
After updating from 3.1.4 to 3.1.5 my php error log is filled with entries like:
[04-Nov-2010 06:42:41] PHP Warning: include(): apc failed to locate ./lib/include2.php - bailing in /home/pierre/public_html/apc-test/lib/include.php on line 5
This only happens with stat=0 and if the file to include has been given a relative path to the initial called script.
I have seen this with using FluxBB btw.. If this is just a new warning which wasn't simply shown in previous apc versions I'll report a bug there to use absolute path for including files.
Reproduce code:
---------------
Here is some example code with the following files:
apc-test
├── lib
│?? ├── include2.php
│?? └── include.php
└── test.php
test.php:
<?php
define('l', './lib/');
echo 4;
if (file_exists(l.'include.php')) {
include(l.'include.php');
}
?>
include.php:
<?php
echo 2;
include(l.'include2.php');
?>
include2.php:
<?php
echo '!';
?>
Actual result:
--------------
Although the code is executed as expected PHP logs the warning mentioned above.
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Dec 04 21:00:02 2025 UTC |
That's really a bug, not a feature. So initially, apc.stat=0 was supposed to work only if every path was a full path. In apc-3.1.4, an include "./lib/include.php" would trigger a stat on every directory in the include_path while it gropes about looking for that file. Assuming your include_path said "/usr/share/pear;/var/www/html/includes:." it would stat 3 times with stat("/usr/share/pear/./lib/include2.php") stat("/var/www/html/includes/./lib/include2.php") stat("././lib/include2.php") Now, the last one succeeds. But this is obviously broken badly w.r.to performance. So I made it look for only in the __DIR__ of the file that was including it. So here, it's looking for it in /home/pierre/public_html/apc-test/lib/lib/include2.php which obviously doesn't exist. So, if you do care about performance, I'd like to break this bit of code, just to squeeze that much more extra from the code. All it needs to be fixed is a define('l', __DIR__.'/lib/'); And you're going to get rid of any extra stats.These messages should probably be changed from apc_warning to apc_debug. Many other similar messages do not generate warnings. patch: Index: apc_cache.c =================================================================== --- apc_cache.c (revision 305202) +++ apc_cache.c (working copy) @@ -859,12 +859,12 @@ fileinfo = apc_php_malloc(sizeof(apc_fileinfo_t) TSRMLS_CC); if (apc_search_paths(filename, include_path, fileinfo TSRMLS_CC) != 0) { - apc_warning("apc failed to locate %s - bailing" TSRMLS_CC, filename); + apc_debug("apc failed to locate %s - bailing" TSRMLS_CC, filename); goto cleanup; } if(!realpath(fileinfo->fullpath, APCG(canon_path))) { - apc_warning("realpath failed to canonicalize %s - bailing" TSRMLS_CC, filename); + apc_debug("realpath failed to canonicalize %s - bailing" TSRMLS_CC, filename); goto cleanup; }apc.stat = 0 doesn't work with relative paths. If it is a relative path, it does a stat(). It used to do a stat() for every path in the include_path, which was destroying the purpose of using no-stat in the first place. for reference include_once("foo.php"); with include_path = /usr/share/php:/usr/lib/php/:. does lstat("/usr/share/php/foo.php"); // if that fails lstat("/usr/lib/php/foo.php"); // if that fails getcwd(); lstat("/var/www/html/foo.php"); lstat("/var"); lstat("/var/www"); lstat("/var/www/html"); open("/var/www/html/foo.php"); It no longer does any of the stat calls (or a realpath()), to look for a file. And that's not a bug. Remember, it *never* used to work right. Now it throws a warning about it not working, so that you can go fix the code.