Edit report at http://bugs.php.net/bug.php?id=52312&edit=1
ID: 52312 Updated by: paj...@php.net Reported by: v dot damore at gmail dot com Summary: PHP lstat problem Status: Bogus Type: Bug Package: Safe Mode/open_basedir Operating System: Linux PHP Version: 5.2.13 New Comment: That's why the setting realpath_cache_size and TTL exist. They allow you to fine tune this cache to fit your needs. On a shared host you will certainly increase the default value. Previous Comments: ------------------------------------------------------------------------ [2010-07-12 14:16:59] v dot damore at gmail dot com Thanks for your explanation, I followed your suggestions and there is a performance improvement in submitted case. Anyway your suggestions are not applicable in all cases. Please consider this problem from my point of view: in a production environment of a big web hosting provider. In this real case there are many thousands of users that can freely write their own PHP code, there also are hundreds of thousands of pages that cannot be cached. Please consider also that what happens when Google spiders come to crawl all pages. ------------------------------------------------------------------------ [2010-07-12 13:49:38] ras...@php.net There is a realpath cache that gets populated, so you need to warm up the cache and not strace the first request. You shouldn't care that the first request to the server takes a few more stats. The real test is whether subsequent requests are slow. If you are seeing excessive stats with the caches warmed up, then you need to investigate the size of your realpath cache in your php.ini and possibly increase it. This part has been made more efficient in PHP 5.3. It would also be a good idea to turn off AllowOverride in your Apache config to get rid of the .htaccess stats if you are concerned about the number of stat calls. So, do this. Start Apache in non-forking mode by running it with -X Then hit a simple hello_world.php script a few times. Don't use phpinfo because it does a number of evil things on its own. After hitting your hello world script a couple of times, attach strace to the Apache process (strace -p <pid>) and then hit the server again once. At this point you should not see any extra stats. ------------------------------------------------------------------------ [2010-07-12 10:03:42] v dot damore at gmail dot com Description: ------------ PHP lstat full pathname many times (at least 4) before read the file is looking for. This behavior appear when in apache httpd configuration is specified PHP_ADMIN_VALUE open_basedir or safe_mode is On. Test script: --------------- To reproduce the problem please create a page phpinfo.php: "<? phpinfo() ?>". I have httpd.2.2.15, PHP 5.2.13. [r...@svilpar4 ~]# /usr/local/apache2/bin/httpd -V Server version: Apache/2.2.15 (Unix) Server built: Jul 9 2010 17:30:06 Server's Module Magic Number: 20051115:24 Server loaded: APR 1.2.7, APR-Util 1.2.7 Compiled using: APR 1.2.7, APR-Util 1.2.7 Architecture: 64-bit Server MPM: Prefork threaded: no forked: yes (variable process count) Server compiled with.... -D APACHE_MPM_DIR="server/mpm/prefork" -D APR_HAS_SENDFILE -D APR_HAS_MMAP -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled) -D APR_USE_SYSVSEM_SERIALIZE -D APR_USE_PTHREAD_SERIALIZE -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT -D APR_HAS_OTHER_CHILD -D AP_HAVE_RELIABLE_PIPED_LOGS -D DYNAMIC_MODULE_LIMIT=128 -D HTTPD_ROOT="/usr/local/apache2" -D SUEXEC_BIN="/usr/local/apache2/bin/suexec" -D DEFAULT_PIDLOG="logs/httpd.pid" -D DEFAULT_SCOREBOARD="logs/apache_runtime_status" -D DEFAULT_LOCKFILE="logs/accept.lock" -D DEFAULT_ERRORLOG="logs/error_log" -D AP_TYPES_CONFIG_FILE="conf/mime.types" -D SERVER_CONFIG_FILE="conf/httpd.conf" [r...@svilpar4 ~]# /usr/local/php5.2.13/bin/php -v PHP 5.2.13 (cli) (built: Jul 1 2010 16:02:03) Copyright (c) 1997-2010 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies Now we specify PHP_ADMIN_VALUE open_basedir</strong> in Virtual host configuration: <Directory "/usr/local/myspace/webspace/httpdocs"> PHP_ADMIN_VALUE open_basedir "/usr/local/myspace/webspace" </Directory> <VirtualHost *:80> ServerName damorealt.xoom.it DocumentRoot "/usr/local/myspace/webspace/httpdocs" CustomLog /var/log/httpd/damorealt/access_log combined ErrorLog /var/log/httpd/damorealt/error_log </VirtualHost > Stop & start apache httpd, "strace -f" all httpd instances and then call page http://damorealt.xoom.it/phpinfo.php, so we can reproduce behavior Expected result: ---------------- If PHP_ADMIN_VALUE open_basedir "/usr/local/myspace/webspace" is removed and safe_mode is Off : 226235 accept(3, {sa_family=AF_INET, sin_port=htons(59366), sin_addr=inet_addr("212.48.14.186")}, [17179869200]) = 15 26235 getsockname(15, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("151.99.197.198")}, [17179869200]) = 0 26235 fcntl(15, F_GETFL) = 0x2 (flags O_RDWR) 26235 fcntl(15, F_SETFL, O_RDWR|O_NONBLOCK) = 0 26235 read(15, "GET /phpinfo.php HTTP/1.0\r\nUser-"..., 8000) = 129 26235 gettimeofday({1278696735, 988799}, NULL) = 0 26235 stat("/usr/local/myspace/webspace/httpdocs/phpinfo.php", {st_mode=S_IFREG|0644, st_size=16, ...}) = 0 26235 open("/usr/local/myspace/.htaccess", O_RDONLY) = -1 ENOENT (No such file or directory) 26235 open("/usr/local/myspace/webspace/.htaccess", O_RDONLY) = -1 ENOENT (No such file or directory) 26235 open("/usr/local/myspace/webspace/httpdocs/.htaccess", O_RDONLY) = -1 ENOENT (No such file or directory) 26235 open("/usr/local/myspace/webspace/httpdocs/phpinfo.php/.htaccess", O_RDONLY) = -1 ENOTDIR (Not a directory) 26235 setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={20, 0}}, NULL) = 0 26235 rt_sigaction(SIGPROF, {0x2afef587dd80, [PROF], SA_RESTORER|SA_RESTART, 0x3916e302d0}, {SIG_DFL, [], 0}, 8) = 0 26235 rt_sigprocmask(SIG_UNBLOCK, [PROF], NULL, 8) = 0 26235 getcwd("/"..., 4095) = 2 26235 chdir("/usr/local/myspace/webspace/httpdocs") = 0 water boiling point 26235 time(NULL) = 1278696735 26235 lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 26235 lstat("/usr/local", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 26235 lstat("/usr/local/myspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 26235 lstat("/usr/local/myspace/webspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 26235 lstat("/usr/local/myspace/webspace/httpdocs", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 26235 lstat("/usr/local/myspace/webspace/httpdocs/phpinfo.php", {st_mode=S_IFREG|0644, st_size=16, ...}) = 0 And read the file. 26235 open("/usr/local/myspace/webspace/httpdocs/phpinfo.php", O_RDONLY) = 16 26235 fstat(16, {st_mode=S_IFREG|0644, st_size=16, ...}) = 0 26235 read(16, "<? phpinfo() ?>\n", 8192) = 16 26235 read(16, "", 8192) = 0 26235 read(16, "", 8192) = 0 26235 close(16) = 0 26235 uname({sys="Linux", node="svilpar4", ...}) = 0 26235 time(NULL) = 1278696735 26235 writev(15, [{"HTTP/1.1 200 OK\r\nDate: Fri, 09 J"..., 173}, {"<!DOCTYPE html PUBLIC \"-//W3C//D"..., 4109}, {"<table border=\"0\" cellpadding=\"3"..., 4101}], 3) = 8383 26235 writev(15, [{"<tr><td class=\"e\">highlight.bg</"..., 4105}, {"sendmail_from</td><td class=\"v\">"..., 4099}], 2) = 8204 26235 time(NULL) = 1278696735 26235 writev(15, [{" </td></tr>\n<tr><td class=\"e\">HT"..., 4108}, {"</td><td class=\"v\">1024</td><td "..., 4098}], 2) = 8206 26235 writev(15, [{"md2 md4 md5 sha1 sha256 sha384 s"..., 4098}, {" </td></tr>\n</table><br />\n<tabl"..., 4106}], 2) = 8204 26235 writev(15, [{"session.use_cookies</td><td clas"..., 4104}, {" </td><td class=\"v\">enabled </td"..., 4102}], 2) = 8206 26235 chdir("/") = 0 26235 setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={0, 0}}, NULL) = 0 26235 writev(15, [{"\"]</td><td class=\"v\">Keep-Alive<"..., 4206}], 1) = 4206 26235 write(10, "212.48.14.186 - - [09/Jul/2010:1"..., 116) = 116 26235 shutdown(15, 1 /* send */) = 0 26235 poll([{fd=15, events=POLLIN}], 1, 2000) = 1 ([{fd=15, revents=POLLIN|POLLHUP}]) 26235 read(15, "", 512) = 0 26235 close(15) = 0 26235 read(4, 0x7fff615ff5eb, 1) = -1 EAGAIN (Resource temporarily unavailable) 26235 accept(3, Actual result: -------------- If PHP_ADMIN_VALUE open_basedir "/usr/local/myspace/webspace" is set and safe_mode is On : 25933 accept(3, {sa_family=AF_INET, sin_port=htons(47433), sin_addr=inet_addr("212.48.14.186")}, [17179869200]) = 15 25933 getsockname(15, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("151.99.197.198")}, [17179869200]) = 0 25933 fcntl(15, F_GETFL) = 0x2 (flags O_RDWR) 25933 fcntl(15, F_SETFL, O_RDWR|O_NONBLOCK) = 0 25933 read(15, "GET /phpinfo.php HTTP/1.0\r\nUser-"..., 8000) = 129 25933 gettimeofday({1278695388, 52976}, NULL) = 0 25933 stat("/usr/local/myspace/webspace/httpdocs/phpinfo.php", {st_mode=S_IFREG|0644, st_size=16, ...}) = 0 25933 open("/usr/local/myspace/.htaccess", O_RDONLY) = -1 ENOENT (No such file or directory) 25933 open("/usr/local/myspace/webspace/.htaccess", O_RDONLY) = -1 ENOENT (No such file or directory) 25933 open("/usr/local/myspace/webspace/httpdocs/.htaccess", O_RDONLY) = -1 ENOENT (No such file or directory) 25933 open("/usr/local/myspace/webspace/httpdocs/phpinfo.php/.htaccess", O_RDONLY) = -1 ENOTDIR (Not a directory) 25933 setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={20, 0}}, NULL) = 0 25933 rt_sigaction(SIGPROF, {0x2b80442fdd80, [PROF], SA_RESTORER|SA_RESTART, 0x3916e302d0}, {SIG_DFL, [], 0}, 8) = 0 25933 rt_sigprocmask(SIG_UNBLOCK, [PROF], NULL, 8) = 0 25933 getcwd("/"..., 4095) = 2 25933 chdir("/usr/local/myspace/webspace/httpdocs") = 0 water boiling point 25933 lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace/httpdocs", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace/httpdocs/phpinfo.php", {st_mode=S_IFREG|0644, st_size=16, ...}) = 0 First check 25933 lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace/httpdocs", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace/httpdocs/phpinfo.php", {st_mode=S_IFREG|0644, st_size=16, ...}) = 0 Second check 25933 lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 Third check (incomplete) 25933 lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace/httpdocs", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace/httpdocs/phpinfo.php", {st_mode=S_IFREG|0644, st_size=16, ...}) = 0 Final check and then read the file. 25933 open("/usr/local/myspace/webspace/httpdocs/phpinfo.php", O_RDONLY) = 16 25933 fstat(16, {st_mode=S_IFREG|0644, st_size=16, ...}) = 0 25933 read(16, "<? phpinfo() ?>\n", 8192) = 16 25933 read(16, "", 8192) = 0 25933 read(16, "", 8192) = 0 25933 close(16) = 0 ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/bug.php?id=52312&edit=1