Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

getCachedTimestamp - cache bug
Goto page 1, 2  Next
 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Bugs
View previous topic :: View next topic  
Author Message
maarchewa
Smarty n00b


Joined: 22 Aug 2011
Posts: 3

PostPosted: Mon Aug 22, 2011 12:24 pm    Post subject: getCachedTimestamp - cache bug Reply with quote

Smarty version: 3.0.6
file: smarty_internal_cacheresource_file.php
function: getCachedTimestamp
details:

current function code:
Code:

    public function getCachedTimestamp($_template)
    {
        // return @filemtime ($_template->getCachedFilepath());
        return ($_template->getCachedFilepath() && file_exists($_template->getCachedFilepath())) ? filemtime($_template->getCachedFilepath()) : false ;
    }


The problem is that file can be deleted between file existance check and file modification time check. In my web app (with cache enabled) about 10% of requests lands with E_WARNING notification (generated by filemtime function).

When I terminate application on E_WARNING notification I can realize that checked file DOES NOT exist (even if existance was checked).

Please add error suppression to the filemtime function (code that was commented out was correct).
Back to top
View user's profile Send private message
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Mon Aug 22, 2011 4:41 pm    Post subject: Re: getCachedTimestamp - cache bug Reply with quote

maarchewa wrote:
Please add error suppression to the filemtime function (code that was commented out was correct).


Smarty 3.1 should already solve the issue
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
maarchewa
Smarty n00b


Joined: 22 Aug 2011
Posts: 3

PostPosted: Tue Aug 23, 2011 11:13 am    Post subject: Reply with quote

problem still exists in version 3.1RC1

E_WARNING is generated in smarty_internal_cacheresource_file.php in process function:

Code:
smarty_internal_cacheresource_file.php:78 - 2:
include(xxx) [<a href='function.include'>function.include</a>]: failed to open stream: No such file or directory


Proposed solution:
- smarty_internal_cacheresource_file.php:78 function process, from
Code:
return include $_template->cached->filepath;

to
Code:
return @include $_template->cached->filepath;


- smarty_cacheresource.php:241 function __constructor, from
Code:

$handler->process($_template)
$this->processed = true;

to
Code:

if($handler->process($_template) === false)
    $this->valid = false;
else {
    $this->processed = true;
}


Please let me know if proposed solution is correct - no notification is generated and everything seems to be fine but I need to be sure Smile
Back to top
View user's profile Send private message
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Tue Aug 23, 2011 11:42 am    Post subject: Reply with quote

Ah, I see. It's not fixed for the filesystem implementation.

Your proposed fix is bad, as it doesn't "fix" anything, just masks an error. You see, the include fails, thus the cache cannot be read, thus smarty would output an empty page. NOT what you expect to happen.

What we have to do here is making sure the cached content is read to memory the instant we get a timestamp (cache hit). Thus the running process must not access the cache a second time.

The main problem will be having to use eval() instead of include. eval() is slow as resulting op-code is currently not cachable by any means (APC and co). I'll discuss the issue with Uwe once he's back.
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Fri Aug 26, 2011 8:31 pm    Post subject: Reply with quote

The proposed solution for 3.1 alone did not cover all possible cases.

The complete fix is in the Smarty_3_1_DEV SVN branch now.
Back to top
View user's profile Send private message
pitbull82
Smarty Rookie


Joined: 01 Feb 2006
Posts: 18
Location: Poland

PostPosted: Tue Sep 20, 2011 11:15 am    Post subject: Reply with quote

Hello

Is this fix in distribution directory in SVN? If so, I think that there's still a problem with caching.

I got notices:

PHP Warning (2): filemtime() [<a href='function.filemtime'>function.filemtime</a>]: stat failed for D:\webmaster\www_wamp\xxx\app\View-Compiled\pl\c8\bf\f2\c8bff2b2f6d7bd060b1a0aba9fc49589387b6345.file.ranking.tpl.php in D:\webmaster\www_wamp\xxx\libs\templates31dev\sysplugins\smarty_resource.php:607

or

PHP Warning (2): unlink(D:\webmaster\www_wamp\xxx\app\View-Compiled\pl\c8\bf\f2\c8bff2b2f6d7bd060b1a0aba9fc49589387b6345.file.ranking.tpl.php) [<a href='function.unlink'>function.unlink</a>]: No such file or directory in D:\webmaster\www_wamp\xxx\libs\templates31dev\sysplugins\smarty_internal_write_file.php:49

The problem occurs on windows and also on unix based systems - please fix it quickly - it's very hard to find other problems in error logs Wink
Back to top
View user's profile Send private message
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Tue Sep 20, 2011 11:36 am    Post subject: Reply with quote

pitbull82 wrote:
Is this fix in distribution directory in SVN? If so, I think that there's still a problem with caching.


There is no problem with caching. The lines of code you refer to will not output any warnings, unless you've declared your own error_handler - and therein failed to respect the error_level.

Please scan your code for use of http://php.net/set_error_handler and fix your handler to ignore
Code:
$errno && ($error & error_reporting())
.
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
Setor
Smarty Rookie


Joined: 12 Nov 2009
Posts: 5

PostPosted: Tue Sep 20, 2011 1:14 pm    Post subject: Reply with quote

Smarty 3.1

Code:

file: smarty_resource.php
line: 599

$compiled->timestamp = @filemtime($compiled->filepath);
$compiled->exists = !!$compiled->timestamp;


Warning: filemtime(): stat failed for ..

Code:

file: smarty_internal_file_write.php
line: 49

unlink($_filepath);


Oh my god... Tricks with error_reporting is very bad style!

Good bye Smarty, hello Twig!
Back to top
View user's profile Send private message
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Tue Sep 20, 2011 1:21 pm    Post subject: Reply with quote

Setor wrote:
Oh my god... Tricks with error_reporting is very bad style!


I don't disagree. But in PHP's current state there is no other way. There is no way to make certain functions atomic. Thus there is no way to make sure that between a file_exists() and a filemtime() call some other process did not delete the file. As you can infer from a valid mtime that the file exists, it's only logic to avoid the file_exists() call altogether.

I havent looked too closely at Twig (or any other engine, for that matter). I don't believe they solved this (if at all) any other way.
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
Setor
Smarty Rookie


Joined: 12 Nov 2009
Posts: 5

PostPosted: Tue Sep 20, 2011 1:50 pm    Post subject: Reply with quote

I understand you, but i catch all warnings and notices. And many frameworks have custom error handlers. My general rule is: Notice/Warning = fatal error.
Back to top
View user's profile Send private message
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Tue Sep 20, 2011 2:02 pm    Post subject: Reply with quote

Setor wrote:
I understand you, but i catch all warnings and notices. And many frameworks have custom error handlers. My general rule is: Notice/Warning = fatal error.


I don't know a single library that would comply with your statement. There are simple things like @mkdir($path, $mode, true), @unlink($path), … that just don't _need_ the file_exists() checks up front. Then there's the race condition problem mentioned above. There are situations where you really just want to, or even need to, ignore a warning.

Well, anyways. We use error suppression at points we feel we _need_ them. We know what we're doing and usually have a pretty good reason for doing so.

(yes, we even test performance differences of @, error_reporting() and set_error_handler() before going with any of them.)
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
pitbull82
Smarty Rookie


Joined: 01 Feb 2006
Posts: 18
Location: Poland

PostPosted: Tue Sep 20, 2011 4:36 pm    Post subject: Reply with quote

Yes, I use error handlers but in my application I want to have all errors, notices and warnings in my log because they are potential problems.

My point of view is that any library I use shouldn't generate any warnings and notices when it's working fine. It should be done be library to handle them properly.

In addition I set my errors to

Code:

   ini_set('display_errors','0');
   ini_set("log_errors" , "1");
   ini_set("error_log" , 'file.txt');
   error_reporting(0);


so using

Code:
$errno && ($error & error_reporting())


makes that I won't have any errors in my log.
Back to top
View user's profile Send private message
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Tue Sep 20, 2011 5:23 pm    Post subject: Reply with quote

we could wrap the fetch() method:
Code:
function fetch() {
  // mute errors that are masked by @silence or error_reporting level
  // but have all other errors bubble through to the next handler
  set_error_handler(function($errno){
    return $errno && $errno & error_reporting();
  });
  // execute template stuff
  parent::fetch();
  // restore previous handler
  restore_error_handler();
}


with that in place, your error handler is not invoked when we don't want it to be. This being an overhead for most people, I'd make it an opt-in feature.

Something you could live with?
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Wed Sep 21, 2011 10:22 pm    Post subject: Reply with quote

I implemented this error muting and committed it to trunk. For those of us not using broken error handlers, it can be disabled with
Code:
Smarty::$error_muting = false;

_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
pitbull82
Smarty Rookie


Joined: 01 Feb 2006
Posts: 18
Location: Poland

PostPosted: Thu Sep 22, 2011 9:24 pm    Post subject: Reply with quote

It seems that's what I excpected - no warnings generated by Smarty - now it's much easier to read log and find bugs in your application (I've just found one ). Thanks!
Back to top
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Bugs All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP