TIP: Use Markdown or, <pre> for multi line code blocks / <code> for inline code.
These forums are read-only and for archival purposes only!
Please join our new forums at discourse.kohanaframework.org
Cache: unlink() causes "Permission denied" warning when cached item expires
  • I am working with the Cache class and I get this warning every time a cached item expires:

    Warning: unlink(D:\Web\htdocs\blog\application\cache\69\69df64f0c15d65ec23bd4541fe1fc8ec4de32234.cache) [<a href='function.unlink'>function.unlink</a>]: Permission denied in D:\Web\htdocs\blog\modules\cache\classes\kohana\cache\file.php on line 347
    Call Stack
    #   Time    Memory   Function                                            Location
    1   0.0011  338872   {main}( )                                           ..\index.php:0
    2   0.0478  657032   Kohana_Request->execute( )                          ..\index.php:70
    3   0.0478  657032   Kohana_Request_Client->execute( )                   ..\request.php:1138
    4   0.0478  657032   Kohana_Request_Client_Internal->execute_request( )  ..\client.php:64
    5   0.0540  708432   ReflectionMethod->invoke( )                         ..\internal.php:118
    6   0.0540  708448   Controller_Welcome->action_index( )                 ..\internal.php:118
    7   0.0735  1018168  Blog::ido( )                                        ..\welcome.php:11
    8   0.0735  1018408  Kohana_Cache_File->get( )                           ..\blog.php:11
    9   0.0739  1037120  Kohana_Cache_File->_delete_file( )                  ..\file.php:165
    10  0.0741  1037344  unlink ( )
    

    (#7 does a DB::select() query, which is cached for 10 seconds)

    Looking at the call stack I went through #8-10, in file "./modules/cache/classes/kohana/cache/file.php":

    124. public function get($id, $default = NULL)
    125. {
    ...
    132.     // Open file
    133      $file = new SplFileInfo($directory.$filename);
    ...
    145.       $data     = $file->openFile();
    ...
    162.        if (($created + (int) $lifetime) < time())
    163.        {
    164.          // Delete the file
    165.          $this->_delete_file($file, NULL, TRUE);
    166.          return $default;
    167.        }
    

    The get() method opens the file on line 145 and then the deletion of the file is delegated to _delete_file() on line 165.

    315.  protected function _delete_file(SplFileInfo $file, $retain_parent_directory = FALSE, $ignore_errors = FALSE, $only_expired = FALSE)
    316.  {
    ...
    346.      if ($delete === TRUE)
    347.        return unlink($file->getRealPath());
    

    The _delete_file() method then unlinks the file at line 347, generating a "Permission denied" warning.

    That is as far as I have gotten.

    The SplFileObject that is returned on line 145 may be the reason. Presumably it locks the file in order to read from it. When the file is then unlinked maybe that lock prevents it from being deleted?

  • You need to check windows permissions/security

  • Yeah, I thought so too, but unlink() works just fine.

    I dropped "test.txt" files into the root folder and into "application/cache/", and then unlink()ed them from the top of index.php, and they are deleted just fine.

    The problem only seems to be with the Cache class.

  • Your web server runs as a different user; post what permissions are on the application folder (or just cache and logs)

  • This has nothing to do with permissions.

    This works:

    <?
    $file = 'application/cache/test.txt';
    file_put_contents($file, 'Some data...');
    unlink($file);
    ?>
    

    And this generates a "Permission denied" warning:

    <?
    $file = 'application/cache/test.txt';
    file_put_contents($file, 'Some data...');
    $info = new SplFileInfo($file);
    $data = $info->openFile();
    return unlink($info->getRealPath());
    ?>
    

    The first example simply creates a file and then unlinks it.

    The second example is how the Cache class does it. It first reads from the file and then deletes it.

    If this had anything to do with permissions then both examples would fail. Only the second does. If you are on Linux then the two examples may not work like on Windows.

  • Okay, the following code fixes the problem for me (lines 59-65):

    ./application/classes/cache/file.php

    http://pastebin.com/VxG07QYd

    I do not have access to a Linux server ATM so it assumes that the problem only occurs on Windows.

  • I can confirm that Sverri's patch does work as he describes it and that the unlink() problem with Windows is a known issue. Any objects residing in memory that hold a handle on the file will prevent it from being deleted. Permissions are not the issue, hanging references are. The object should probably be unset on ALL platforms, it's just required in Windows. It should probably be rolled into the core.

  • Thanks. The patch is work.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion