Edit report at https://bugs.php.net/bug.php?id=63413&edit=1
ID: 63413
Comment by: giunta dot gaetano at gmail dot com
Reported by: ben at indietorrent dot org
Summary: Intermittent warning and fatal error on require()
statement
Status: Open
Type: Bug
Package: Scripting Engine problem
Operating System: Windows 7 x64
PHP Version: 5.4.8
Block user comment: N
Private report: N
New Comment:
A behaviour which has been puzzling me and that might (or not) be related: we
also have some failing code which assumes that filemtime should not be zero
(for an existing file). This is generally happening on Linux servers at
customers (php in mode_prefork), at times of high load, for nfs-mounted files
Previous Comments:
------------------------------------------------------------------------
[2012-11-16 16:29:11] ben at indietorrent dot org
Additional testing indicates that this problem is likely related to a specific
piece of software that has been installed on the affected machines, and not PHP
or the manner in which it is integrated with Apache.
I tested the steps-to-reproduce with the exact same project/code-base on a LAMP
stack (Ubuntu 12.04 + Apache 2.2.22 + MySQL 5.5.24 + PHP 5.3.10) and cannot
reproduce the issue, no matter how hard I hammer the server with requests.
As mentioned previously, I am unable to reproduce this issue with a comparable
stack on Mac OS 10.8, either.
These facts pointed to a Windows-specific cause, perhaps related to Apache's
"winnt" MPM, so I setup a VM with a pristine Windows 7 x86 installation. I
installed the same stack components as are installed on the computers on which
this issue occurs. Yet, after several hours of hammering the server with
constant page-requests, not a single error has been registered in PHP's error
log.
If at any point I'm able to determine which software causes this issue, I will
post my findings here.
------------------------------------------------------------------------
[2012-11-05 15:45:02] ben at indietorrent dot org
Another update.
I began to suspect that this is a thread-safety issue, so I downloaded the
latest non-thread-safe version of PHP and configured Apache to serve PHP files
via Fast-CGI (mod_fcgid).
To my surprise, this problem still occurs, and it seems to be worse with
Fast-CGI than with Mod-PHP.
Also, I tried to reproduce the problem on a Mac with Mac OS 10.8 and a fairly
modern MAMP installation that runs PHP via Mod-PHP. No matter how hard I
hammered on Apache, these spurious require() failures did not occur.
------------------------------------------------------------------------
[2012-11-01 21:07:42] ben at indietorrent dot org
It occurred to me to examine Apache's internal error log for entries that
correspond to those in PHP's error log when this occurs. I noticed what may be
an important clue.
Sample entries in PHP's error log:
-----------------------
[01-Nov-2012 13:29:41 America/New_York] PHP Warning:
require(../include/global.inc.php): failed to open stream: No such file or
directory in C:\Users\Ben\Documents\Projects\project
Testing\project-svn\trunk\public\auxiliary\css.php on line 5
[01-Nov-2012 13:29:41 America/New_York] PHP Fatal error: require(): Failed
opening required '../include/global.inc.php' (include_path='.;C:\Program
Files\php\includes;C:\Program Files\php\PEAR\pear') in
C:\Users\Ben\Documents\Projects\project
Testing\project-svn\trunk\public\auxiliary\css.php on line 5
[01-Nov-2012 13:29:43 America/New_York] PHP Warning:
require(C:/Users/Ben/Documents/Apache/project/protected/constants.inc.php):
failed to open stream: No such file or directory in
C:\Users\Ben\Documents\Projects\project
Testing\project-svn\trunk\public\include\global.inc.php on line 18
[01-Nov-2012 13:29:43 America/New_York] PHP Fatal error: require(): Failed
opening required
'C:/Users/Ben/Documents/Apache/project/protected/constants.inc.php'
(include_path='.;C:\Program Files\php\includes;C:\Program Files\php\PEAR\pear')
in C:\Users\Ben\Documents\Projects\project
Testing\project-svn\trunk\public\include\global.inc.php on line 18
-----------------------
Roughly-corresponding entries in Apache's error log:
-----------------------
[Thu Nov 01 13:29:21.235844 2012] [core:error] [pid 6780:tid 1136] (OS 32)The
process cannot access the file because it is being used by another process. :
[client 10.0.1.57:65162] AH00127: Cannot map GET
/project/public/js/jquery.accordion.js HTTP/1.1 to file, referer:
https://ben-pc/project/public/company/history/
[Thu Nov 01 13:29:41.141441 2012] [core:error] [pid 6780:tid 1128] (OS 32)The
process cannot access the file because it is being used by another process. :
[client 10.0.1.57:65204] AH00127: Cannot map GET
/project/public/common/js/libs/modernizr-2.5.3.min.js HTTP/1.1 to file,
referer: https://ben-pc/project/public/contact/service-inquiry/
-----------------------
While I don't see any direct correlation between the files cited in PHP's error
log and those cited in Apache's error log, the message "(OS 32)The process
cannot access the file because it is being used by another process" seems very
relevant to the observed behavior in PHP.
This observation inspired me to create a very simple test script which, much to
my surprise, enables me to produce this issue at will. I was able to reproduce
the issue in Windows' Safe Mode, too, which seems to eliminate virus scanners,
filter drivers, and other similar causes.
The key to reproducing this issue is making as many requests per unit of time
as possible. In other words, holding-down the browser's refresh key (e.g.,
Ctrl+R or F5) for some period of time eventually causes require() failures to
be logged.
Here's the script:
<?php
$file = 'C:/Users/Ben/Documents/Apache/require-test-include.php';
$counter = 0;
while ($counter < 500) {
require($file);
flush();
$counter++;
}
?>
The contents of "require-test-include.php" are probably largely irrelevant, but
I'm using the following:
<?php
echo '.';
?>
A sample excerpt from PHP's error log contains entries such as the following:
-----------------------
[01-Nov-2012 16:01:53 America/New_York] PHP Warning:
require(C:/Users/Ben/Documents/Apache/require-test-include.php): failed to open
stream: No such file or directory in
C:\Users\Ben\Documents\Apache\require-test.php on line 8
[01-Nov-2012 16:01:53 America/New_York] PHP Fatal error: require(): Failed
opening required 'C:/Users/Ben/Documents/Apache/require-test-include.php'
(include_path='.;C:\Program Files\php\includes;C:\Program Files\php\PEAR\pear')
in C:\Users\Ben\Documents\Apache\require-test.php on line 8
-----------------------
Apache's error log fills-up with entries such as the following (I've included
six lines to demonstrate the timestamp variances):
-----------------------
[Thu Nov 01 15:59:02.327506 2012] [core:error] [pid 4420:tid 1040] (OS 32)The
process cannot access the file because it is being used by another process. :
[client 10.0.1.57:62710] AH00127: Cannot map GET /require-test.php HTTP/1.1 to
file
[Thu Nov 01 15:59:02.389509 2012] [core:error] [pid 4420:tid 1040] (OS 32)The
process cannot access the file because it is being used by another process. :
[client 10.0.1.57:62710] AH00127: Cannot map GET /require-test.php HTTP/1.1 to
file
[Thu Nov 01 15:59:02.954339 2012] [core:error] [pid 4420:tid 748] (OS 32)The
process cannot access the file because it is being used by another process. :
[client 10.0.1.57:62740] AH00127: Cannot map GET /require-test.php HTTP/1.1 to
file
[Thu Nov 01 15:59:03.093347 2012] [core:error] [pid 4420:tid 748] (OS 32)The
process cannot access the file because it is being used by another process. :
[client 10.0.1.57:62747] AH00127: Cannot map GET /require-test.php HTTP/1.1 to
file
[Thu Nov 01 15:59:03.491370 2012] [core:error] [pid 4420:tid 948] (OS 32)The
process cannot access the file because it is being used by another process. :
[client 10.0.1.57:62768] AH00127: Cannot map GET /require-test.php HTTP/1.1 to
file
[Thu Nov 01 15:59:03.758385 2012] [core:error] [pid 4420:tid 1040] (OS 32)The
process cannot access the file because it is being used by another process. :
[client 10.0.1.57:62776] AH00127: Cannot map GET /require-test.php HTTP/1.1 to
file
-----------------------
It is worth noting that requesting a "normal" page from one of my PHP
applications and then switching to this test script immediately thereafter, and
hammering on it with F5, dramatically increases the number of failed require()
occurrences. Conversely, if I hammer on the above script only (and don't browse
to other application URLs on localhost), the frequency of the require()
failures is reduced to only a few per several thousand requests.
As a final point of note, when the file that is passed to require() references
an NTFS junction point (created with "mklink.exe /J"), require() performance is
degraded noticeably (expected, perhaps), which makes this issue easier to
reproduce. This observation may be at the root of
https://bugs.php.net/bug.php?id=39484 ("intermittent include failure under
symlinked virtual hosts").
How can one feel confident in deploying a PHP application that is guaranteed to
be under a heavy load when this type of problem exists? Even if "this is not a
bug", per se, the fact that this scenario is not handled more gracefully
(either in PHP or Apache) is disconcerting, to say the least.
------------------------------------------------------------------------
[2012-11-01 17:04:26] ben at indietorrent dot org
Description:
------------
I observe erratic behavior relating to require() statements. The files that are
being required are static (they are not created or destroyed during script
execution), so there should be no reason that they are required successfully
the vast majority of the time, but fail to be required some small percentage of
the time.
It bears mention that I am also wrapping the calls to require() in calls to
file_exists(). It seems that while file_exists() always returns true (the
require() statements are always executed), the calls to require() fail
intermittently with "PHP Warning: Unknown: failed to open stream: No such file
or directory" and then "PHP Fatal error: Unknown: Failed opening required".
The symptoms of this issue are very similar to those described in
https://bugs.php.net/bug.php?id=49012 ("Spurious fatal error on require()
statement"), but I don't know whether the root cause is the same or not.
I have confirmed that this problem occurs on several different computers, no
two of which have the exact same OS or *AMP stack component versions. For this
reason, I do not believe this issue to be due to failing hardware, a corrupt
operating system, or similar.
I should note also that in PHP 5.2 and 5.3, the offending line number was
always zero (0). Unless line number zero has some special meaning in PHP, this
seems like a bug in itself. In any case, in PHP 5.4.8, the line number is
non-zero *usually* (but not always), and seems to be accurate. (I have not
tested with any PHP version before 5.2 or between 5.3 and 5.4.8.)
I have not installed any third-party extensions and am using a pristine 5.4.8
installation. PHP is running via Apache's mod_php module. php.ini is relatively
untouched; the only changes I made were to enable some of the modules that are
disabled by default (I can list them if it's relevant).
Unfortunately, I am unable to reproduce this issue at will, because it occurs
completely sporadically.
That said, the problem occurs quite frequently, so, if a developer is able to
provide specific debugging instructions, it should be easy enough for me to
capture the relevant information. By "quite frequently", I mean every couple of
minutes during normal browsing.
Also, I have used Firefox's handy "Reload Tab Every..." context menu feature to
reload an affected page every 1 second for 10 minutes straight and the issue
occurred only twice. This seems to indicate that the issue does not necessarily
occur some percentage of the time (+/- variance), but rather, it occurs when
more complex conditions are met. For whatever reason, the issue occurs most
frequently when I make several concurrent requests to the affected URLs/files,
and I navigate to various URLs before each page has loaded fully.
Strangely enough, if I let the auto-refresh test run long enough (this run, it
took more than 30 minutes of refreshing every second), the specific error
messages change (the location of the failed require statements change), but
their nature is always the same: failed require() statements due to variations
of "file not found".
Also, the issue seems most likely to occur when the Web-server (Apache in this
case) has been sitting idle for some period of time (e.g., 10 or more minutes).
Oftentimes, if I have been away from the computer and refresh an affected page
when I return, the issue occurs. Could this behavior point to memory managment
or caching?
The code-base that causes this issue is shared across several different
production websites, all of which run on various GNU/Linux distributions. With
Ubuntu 10.04 + Apache 2.2.14 + mod_php + PHP 5.3.2, I do not observe the issue
at all. On another identically-configured server, the only difference being
Fast-CGI (fcgid) instead of mod_php, I do observe the issue, but its
manifestation is slightly different than on Windows with mod_php. (I'm happy to
provide details regarding the differences.)
I find it particularly strange that the messages and specific points of failure
change over time. The first log entry (made only a few seconds after Apache was
started) makes no sense; there is no file mentioned, and the line number is
zero:
--------------------
[29-Oct-2012 15:30:29 America/New_York] PHP Warning: Unknown: failed to open
stream: No such file or directory in Unknown on line 0
--------------------
At least the related fatal error mentions a file:
--------------------
[29-Oct-2012 15:30:29 America/New_York] PHP Fatal error: Unknown: Failed
opening required
'C:/Users/Ben/Documents/Apache/project/public/auxiliary/css.php'
(include_path='.;C:\Program Files\php\includes;C:\Program Files\php\PEAR\pear')
in Unknown on line 0
--------------------
The next time the warning/fatal occurs, we have a file AND a line number:
--------------------
[29-Oct-2012 15:31:19 America/New_York] PHP Warning:
require(../include/global.inc.php): failed to open stream: No such file or
directory in C:\Users\Ben\Documents\Projects\project
Testing\project-svn\trunk\public\auxiliary\css.php on line 5
[29-Oct-2012 15:31:19 America/New_York] PHP Fatal error: require(): Failed
opening required '../include/global.inc.php' (include_path='.;C:\Program
Files\php\includes;C:\Program Files\php\PEAR\pear') in
C:\Users\Ben\Documents\Projects\project
Testing\project-svn\trunk\public\auxiliary\css.php on line 5
--------------------
I mean... what, does PHP need to "warm-up"?
This warning/fatal sequence carries-on for some minutes, and then the error
(provided this is indeed the same root-cause) morphs slightly:
--------------------
[29-Oct-2012 15:34:07 America/New_York] PHP Fatal error: Uncaught exception
'SmartyException' with message 'Unable to load template file
'C:/Users/Ben/Documents/Apache/project/protected/templates\css/global.css'' in
C:\Users\Ben\Documents\Projects\project
Testing\project-svn\trunk\protected\common\libs\php-classes\external\Smarty-3.1.11\libs\sysplugins\smarty_internal_templatebase.php:127
Stack trace:
#0 C:\Users\Ben\Documents\Projects\project
Testing\project-svn\trunk\protected\common\libs\php-classes\external\Smarty-3.1.11\libs\sysplugins\smarty_internal_templatebase.php(374):
Smarty_Internal_TemplateBase->fetch('C:/Users/Ben/Do...', NULL, NULL, NULL,
true)
#1 C:\Users\Ben\Documents\Projects\project
Testing\project-svn\trunk\public\auxiliary\css.php(75):
Smarty_Internal_TemplateBase->display('C:/Users/Ben/Do...')
#2 {main}
thrown in C:\Users\Ben\Documents\Projects\project
Testing\project-svn\trunk\protected\common\libs\php-classes\external\Smarty-3.1.11\libs\sysplugins\smarty_internal_templatebase.php
on line 127
--------------------
After this point, the errors don't change again.
I have discussed this issue at length on the Smarty forums (
http://www.smarty.net/forums/viewtopic.php?t=23591 ) and the Smarty authors
pointed-out that Smarty throws the above exception when a call to
filemtime($templateSourceFile) returns FALSE (Smarty does not bother to read
the file's contents when filemtime() returns FALSE).
So, we have erroneous failures when require() is called, coupled with erroneous
failures when filemtime() is called.
The path from the above log excerpts, "C:/Users/Ben/Documents/Apache/project",
is an NFTS junction point that resolves to
"C:\Users\Ben\Documents\Projects\project Testing\project-svn\trunk". I'm not
sure that this is relevant, because the errors occur regardless of which path I
use in the calls to require(), but it deserves mention in light of
https://bugs.php.net/bug.php?id=39484 ("intermittent include failure under
symlinked virtual hosts").
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=63413&edit=1