php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72666 touch(): stat cache clearing inconsistent between file:// paths and plain paths
Submitted: 2016-07-25 07:37 UTC Modified: 2023-12-15 13:21 UTC
From: phofstetter at sensational dot ch Assigned:
Status: Open Package: *Directory/Filesystem functions
PHP Version: 7.1.0beta1 OS: MacOS X and Linux
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2016-07-25 07:37 UTC] phofstetter at sensational dot ch
Description:
------------
When calling touch() on a plain path, the stat cache doesn't get cleared. However, when calling touch() on a 'file://' URL, the stat cache gets cleared by virtue of `php_plain_files_metadata` which clears the stat cache after all operations.

This leads to the behaviour as shown in the test script (output available here: https://3v4l.org/0VQIo)

Furthermore: fopen(), fwrite(), fclose() does not clear the stat cache in either case and neither does file_put_contents().

I would create a PR to fix the touch() case, but in general, it's probably worth reconsidering the usefulness of the stat-cache these days. Even over an NFS link, when doing nothing but stat()'ing, you still only lose about 10% performance if you call clearstatcache() after every stat().

Plus, the cache really only helps when you continuously stat() the same file within the same request, which probably isn't correct application behaviour anyways.

So in general, I would propose to actually kill the stat cache which would fix this inconsistency as well :-)

Test script:
---------------
<?php

// doesn't update realpath cache
touch('/tmp/foo');
var_dump(filemtime('/tmp/foo'));
touch('/tmp/foo', 1);
var_dump(filemtime('/tmp/foo'));

// does update the realpath cache
touch('file:///tmp/foo');
var_dump(filemtime('file:///tmp/foo'));
touch('file:///tmp/foo', 1);
var_dump(filemtime('file:///tmp/foo'));

Expected result:
----------------
int(1469202653)
int(1)
int(1469202653)
int(1)

Actual result:
--------------
int(1469202653)
int(1469202653)
int(1469202653)
int(1)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-07-25 11:02 UTC] ab@php.net
As mentioned on ML, I'd doubt the removal is justified. The most of usage scenarios only profit from the caching, while in other cases cache can be explicitly reset. I/O is one of the usual bottlenecks, even today. So more like expected behavior.

Thanks.
 [2016-07-25 11:10 UTC] phofstetter at sensational dot ch
ok. Thank you. 

I'll prepare a PR then that clears the cache when touch() is used.

What about clearing the cache when fopen() is used with any of the writable flags?
 [2021-09-04 19:06 UTC] kevin at lyda dot ie
There are a long list of functions that would need to be updated as this is due to the stat cache. Among the functions that would need to be updated: touch(), fopen(), fread(), fwrite(). The unlink() function already does the update. There's also an argument that exec() and related functions should be updated to invalidate the stat cache.

See bug 28790 for more info and a possible, more reliable, solution.
 [2022-02-13 03:02 UTC] requinix@php.net
-Block user comment: No +Block user comment: Yes
 [2023-12-15 13:21 UTC] bukka@php.net
I have to say I'm a bit doubtful of stat cache advantages but we would need to measure it.

Thinking about this I think it would make sense to fix the mentioned function to clear the stat cache. I'm not sure if we should do that in bug fixing release though but it seems like a clear bug to me so probably yeah.

Changing package as stream part works fine.
 [2023-12-15 13:21 UTC] bukka@php.net
-Package: Streams related +Package: *Directory/Filesystem functions
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 11:01:28 2024 UTC