Apache hangs for five seconds with FallbackResource when accessing `/`
I'm running a standard installation of Apache 2.4.6 (Amazon) with PHP 5.4.21 using the following configuration for my virtual host:
DirectoryIndex index.php
# ...
FallbackResource /index.php
My index.php
is the epitome of simple:
<?php echo "Hello world";
Accessing http://<server-name>/
mysteriously shows the full page only after five seconds! Any other page has the expected response time (which is fast).
Those five seconds, as I came to find out, are related to the default waiting time of the Keep-Alive
feature; in this case, the last few bytes of the chunked response are not sent until Apache severs the connection after that waiting time. Btw, that also completely ruins any gains that a persistent connection would otherwise give you.
Is this a known bug of Apache or am I missing something extremely obvious here?
Solution 1:
2017/04/18: This has been fixed in Apache 2.4.25: https://bz.apache.org/bugzilla/show_bug.cgi?id=58292
The explanation from the bug summary:
If FallBackResource is executed on a subrequest, the server never sends an last-chunk causing the appearance of a hang in some clients.
This happens because the EOS bucket is stripped by the subrequest filter, which is not removed properly if multiple subrequest filters end up in one list
This behaviour is only apparent when compression is applied, because that relies on knowing when the stream ends; and the 5s is the default socket timeout that's used.
Old answer
From this bug report I realised that this problem could be related to the DirectoryIndex
directive.
The standard Apache installation comes with the following section in the configuration:
<IfModule dir_module>
DirectoryIndex index.html
</IfModule>
Any directives following this statement, such as the one in your virtual host, will not overwrite this setting; rather, it gets added to a stack of pages that will be attempted when the index is requested. This behaviour can be confirmed when you perform strace httpd -X
and check the stat()
calls right after the request has been read, e.g.:
stat("/path/to/vhost/index.html", 0x7fff9dc41b90) = -1 ENOENT
stat("/path/to/vhost/index.php", {st_mode=S_IFREG|0664, st_size=130, ...}) = 0
Although I can't tell exactly why, any previous DirectoryIndex
directive must be cleared before specifying DirectoryIndex index.php
, i.e. index.php
MUST be the first page that's attempted to handle the request.
This can be done using the following configuration:
DirectoryIndex disabled
DirectoryIndex index.php