Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

clearByTags in Filesystem adapter crashes when .tag file deleted during GlobIterator loop #44

Closed
skors opened this issue Nov 9, 2015 · 7 comments
Assignees
Labels
Milestone

Comments

@skors
Copy link
Contributor

skors commented Nov 9, 2015

Hi,

we see the following error when using Filesystem storage adapter and deleting a large set of object from cache with clearByTags() method.

// when file_locking is off in File Zend/Cache/Storage/Adapter/Filesystem.php in line 1363
file_get_contents(my_cache_dir/my_cached_object_4711.tag): failed to open stream: No such file or directory
// when file_locking is on in File Zend/Cache/Storage/Adapter/Filesystem.php in line 1327
fopen(my_cache_dir/my_cached_object_4711.tag): failed to open stream: No such file or directory

It is not that easy to reproduce but occurs as follows:

  • the GlobIterator in clearByTags() looks for all .tag files which holds the cached item tags information
  • while looping through these items, another process deletes one item (and its .tag file) which is also prior found by the GlobIterator
  • clearByTags triggers an error at $this->getFileContent($pathname) because fopen() or file_get_contents try to open a non existing file (not existing anymore)

Should be simple be avoided by adding

if (!file_exists($file)) { // or !$glob->valid()?
    continue;
}

to the foreach loop in clearByTags(), but is this right?

I also can submit a PR, but until now i do not have found a way to reproduce for a unit test

cheers

@skors
Copy link
Contributor Author

skors commented Nov 9, 2015

This issue probably also occurs in the other clearBy* methods where the GlobIterator is used as well.

@marc-mabe
Copy link
Member

hi @skors - thanks for your bug report!

This one is really hard to solve and test and it can happen on every function looping over different items.

A simple file_exists doesn't fully solve the issue as first the result of file_exists will be cached by PHP itself and calling clear_stat_cache would totally degree performance and secondly there is still a possible race condition between file_exists and reading the file.

A better solution would be to catch the error on reading the file and afterwords check if the reason of the error is a missing file. Than ignore the error in this case. For removing files there is already a the method Filesystem::unlink that works this way.

@marc-mabe marc-mabe self-assigned this Nov 10, 2015
@marc-mabe marc-mabe added the bug label Nov 10, 2015
@skors
Copy link
Contributor Author

skors commented Nov 11, 2015

@marc-mabe okay. I'll try to work on it and maybe you can take a review if i have understood you correctly

@marc-mabe
Copy link
Member

Nice thanks

@marc-mabe
Copy link
Member

@skors any news ?

@skors
Copy link
Contributor Author

skors commented Feb 18, 2016

@marc-mabe yes, just give me a few days

@skors
Copy link
Contributor Author

skors commented Feb 19, 2016

@marc-mabe please see bugfix/clear-by-tag_on_filesystem-storage branch at skors/zend-cache
https://github.com/skors/zend-cache/tree/bugfix/clear-by-tag_on_filesystem-storage

I've added tests which can reproduce the error now

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants