php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #59536 Relative files are not cached anymore
Submitted: 2010-12-09 12:58 UTC Modified: 2010-12-15 03:33 UTC
From: damien at commerceguys dot com Assigned:
Status: Closed Package: APC (PECL)
PHP Version: 5_2 SVN-2010-12-09 (dev) OS: Linux
Private report: No CVE-ID: None
 [2010-12-09 12:58 UTC] damien at commerceguys dot com
Description:
------------
Starting from APC 3.1.5, and more precisely revision 305003, 
APC file caching is broken for most framework / applications 
that use anchored relative paths like './includes/myfile.inc'.

The core of the issue is that apc_search_paths() considers 
that a relative include like this one is relative to *the 
including file*, not relative to the current working 
directory.

I guess that this patch is not actually the culprit, and that 
it just uncovered a more in-depth bug. It seems that it only 
worked before because '.' is mostly always in the 
include_path.

Reproduce code:
---------------
test.php:
<?php
include_once('./a/include1.php');
?>

a/include1.php:
<?php
include_once('./a/include2.php');
?>

a/include2.php:
<?php
echo "Hello world.");
?>

Expected result:
----------------
Both include1.php and include2.php are cached by APC.

Actual result:
--------------
Stat for include2 fails and APC fallback to 
old_compile_file():

Notice: Unknown: Inserting [/projects/test.lab/www/test.php] 
in Unknown on line 0

Notice: include_once() [function.include-once]: Inserting 
[/projects/test.lab/www/a/include1.php] in 
/projects/test.lab/www/test.php on line 2

Notice: include_once() [function.include-once]: Stat failed 
./a/include2.php - bailing (/projects/test.lab/www/test.php) 
(-1303885627) in /projects/test.lab/www/a/include1.php on line 
2


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-12-09 13:01 UTC] pierre dot php at gmail dot com
Do you use apc.stat=1 or 0?
 [2010-12-09 13:04 UTC] damien at commerceguys dot com
Both apc.stat=0 and apc.stat=1 fail. This is not a duplicate 
of the other issue.
 [2010-12-09 13:05 UTC] damien at commerceguys dot com
This makes APC useless for Drupal (< 7), and I guess for many 
other web frameworks.
 [2010-12-09 13:11 UTC] pierre dot php at gmail dot com
Can you try with 3.1.6 please or even better a svn version?
 [2010-12-09 13:13 UTC] damien at commerceguys dot com
I should have clarified that this behavior is present in 3.1.6 
(which is very sad for the first stable release in years).

I tried with trunk, which also has that behavior. Reverting 
r305003 on top of trunk fixes caching of relative files.
 [2010-12-09 13:34 UTC] pierre dot php at gmail dot com
ok, thanks for the tests!

Will see why it passes through our tests :P
 [2010-12-09 13:47 UTC] pierre dot php at gmail dot com
Gopal, why did we do that by default? I thought the idea was to actually kill relative path and include_path support for apc.stat=0, not for stat=1. That's obviously a bad break, even if using relative path and include path is indeed a bad idea from a perf point of view.
 [2010-12-09 14:50 UTC] gopalv@php.net
The issue really is this assumption I made.

"./x.php" is really dirname(__FILE__)."/x.php"

I can see that it isn't the case, which is weird.

Because in php 5.3 svn, I have the exact same test working.

To make sure we're on the same page for this

gopalv@delta:/opt/php53/var/www$ find 20529/

20529/
20529/index.php
20529/a
20529/a/include2.php
20529/a/include1.php


gopalv@delta:/opt/php53/var/www$ cat 20529/index.php 
<?php

include_once("./a/include1.php");
?>

gopalv@delta:/opt/php53/var/www$ cat 20529/a/include1.php 
<?php

include_once("./a/include2.php");
?>

gopalv@delta:/opt/php53/var/www$ cat 20529/a/include2.php 
<?php
$a = apc_cache_info();
print_r($a["cache_list"]);
print_r(get_include_path());

Now, when I run this

Array
(
    [0] => Array
        (
            [type] => file
..
            [filename] => /opt/php53/var/www/20529/index.php
        )

    [1] => Array
        (
            ...
            [filename] => /opt/php53/var/www/20529/a/include1.php
        )

    [2] => Array
        (
            [filename] => /opt/php53/var/www/20529/a/include2.php
        )

)

/opt/php53/usr/share/php:/opt/php53/lib/php

From all I can tell, it is working exactly as it should.

I might be a little out-of-focus today, so if I did something bad up there, please point it out.
 [2010-12-09 15:16 UTC] damien at commerceguys dot com
Actually, I can confirm that it actually works on PHP 5.3.

I suppose that on PHP 5.3, APC doesn't call 
apc_search_paths() at all 
(maybe rely on sapi_get_stat()?).

I confirmed that it indeed fails on PHP 5.2.

The logic of apc_search_paths() is definitely wrong anyway, 
because 
"./x.php" is really getcwd()."/x.php", not 
dirname(__FILE__)."/x.php".
 [2010-12-10 07:07 UTC] gopalv@php.net
I see how this slipped through my tests.

For include_once(), php resolves the full path before it gets to APC. The same would fail with include("./a/include2.php");

I'll fix this. Thanks for the test case.

And the -stable marker is really for the new allocator implementation than anything else. 

And please do post benchmarks against 3.0.19 vs 3.1.x, for your use case.
 [2010-12-15 03:33 UTC] gopalv@php.net
Here you go

http://news.php.net/php.pecl.cvs/15081

Please check up on this.
 [2011-02-19 05:05 UTC] peterlozano at gmail dot com
Thanks damien and gopalv for this fix.

My Drupal install was also suffering this and it has been a 
pain to debug.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Apr 24 05:01:30 2024 UTC