Smarty Forum Index Smarty
The discussions here are for Smarty, a template engine for the PHP programming language.
Smarty 3.1.8 smarty_internal_write_file.php unlink file

 
Post new topic   Reply to topic    Smarty Forum Index -> Bugs
View previous topic :: View next topic  
Author Message
TheFox
Smarty n00b


Joined: 29 Feb 2012
Posts: 4

PostPosted: Tue Apr 17, 2012 7:05 am    Post subject: Smarty 3.1.8 smarty_internal_write_file.php unlink file Reply with quote

Hi,

since I upgraded to Smarty 3.1.8 I got a
Quote:
error in 'smarty_internal_write_file.php' on line 49: unlink(cache/tpl_c/[...].tpl.php): No such file or directory (2)

every time I clear the compile directory "tpl_c". On the second reload of the page no error appears.

I had the same error in Smarty 3.1.1 but in this version this error doesn't appears so often as in 3.1.8. Why do you not replace the

Code:
@unlink($_filepath);


line with

Code:
if(file_exists($_filepath))
@unlink($_filepath);


?

I also get a
Quote:
error in 'smarty_resource.php' on line 693: filemtime(): stat failed for cache/tpl_c/[...].tpl.php (2)



In both cases why do you not check if the file exists?

Br
Back to top
View user's profile Send private message
rodneyrehm
Administrator


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

PostPosted: Tue Apr 17, 2012 7:57 am    Post subject: Reply with quote

please use Smarty::muteExpectedErrors().
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
TheFox
Smarty n00b


Joined: 29 Feb 2012
Posts: 4

PostPosted: Tue Apr 17, 2012 8:22 am    Post subject: Reply with quote

This doesn't work. I have a own error handler after Smarty::muteExpectedErrors();
Back to top
View user's profile Send private message
rodneyrehm
Administrator


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

PostPosted: Tue Apr 17, 2012 8:35 am    Post subject: Reply with quote

exactly. You have your own error handler which does not respect error_reporting level. You may be doing this on purpose, you may not. The reason behind ignoring the currently set error_reporting-level is irrelevant. What's relevant is, that Smarty relies on a certain default behavior regarding error handling in php.

You basically have 2 options:

1) invoke Smarty::muteExpectedErrors() *after* you registered your own error handler. This handler will filter out all errors Smarty expected and pass the rest to your previously registered handler.
2) fix your error handler
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
TheFox
Smarty n00b


Joined: 29 Feb 2012
Posts: 4

PostPosted: Tue Apr 17, 2012 8:38 am    Post subject: Reply with quote

Ok, thx for the answer. I understand.

But why do you not fix the bugs in Smarty?
Back to top
View user's profile Send private message
rodneyrehm
Administrator


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

PostPosted: Tue Apr 17, 2012 8:57 am    Post subject: Reply with quote

TheFox wrote:
But why do you not fix the bugs in Smarty?


because they aren't bugs.

Code:
if (file_exists($file)) {
  unlink($file);
}


looks like proper and clean code, right? Unless you've ever maintained a reasonably high-traffic site, you won't know much about atomic operations, race conditions, etc. let me point it out:

Code:
if (file_exists($file)) {
  // <- possible race condition can happen here
  unlink($file);
}


As there is no way for declaring a set of operations atomic (meaning they have to be "executed as one operation without interruption") the following scenario isn't very unlikely, once you've reached a certain degree of concurrent traffic:

Quote:
Process 1: file_exists($file) -> yeah, exists
Process 2: remove $file (mustn't even be a php process, could be a cron-triggered shell script or something)
Process 1: unlink($file) -> uhoh, can't unlink 'cause it ain't there!


The whole point of checking if a file exists before unlinking it is to prevent unlink() from throwing errors. But given the above mentioned gateway for race conditions, our file_exists() check doesn't work 100% reliably. We will see sporadic warnings in our error log.

Now that we've established that a file_exists() before an unlink() is not 100% safe, we come to the conclusion to silence the unlink() to ignore the possibly expected error:
Quote:
@unlink($file);


Seeing that unlink() won't do any harm on a file that doesn't exist, and knowing that the file_exists() doesn't really matter anymore, we can simply drop the file_exists() check altogether - unlink() is silenced, so it won't throw a warning anyways.

So much for race conditions. Something most people won't ever really suffer from. But what about general performance? You know that HDDs are slow, right? So you want to minimize HDD access (Disk I/P, stat calls, …). file_exists() and touch() cause 2 stats. @unlink() causes 1 stat. You just reduced Disk I/O of your function by 50%. Awesome job!

now… do you still think this is a bug?

(every time I answer this question I wonder why I can't find one of my old posts to simply link to. Everytime I keep telling myself »Someday, you'll write this elaborate blog about this… someday!«)
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
TheFox
Smarty n00b


Joined: 29 Feb 2012
Posts: 4

PostPosted: Tue Apr 17, 2012 9:04 am    Post subject: Reply with quote

Ah I see, that's a good point of view. I understand, you'r right.
Thanks every much for your explanation.
Back to top
View user's profile Send private message
rodneyrehm
Administrator


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

PostPosted: Tue Apr 17, 2012 10:58 am    Post subject: Reply with quote

Screw it… here's the (more elaborate) blog post on Improving Disk I/O in PHP Apps.
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
antman
Smarty n00b


Joined: 20 Sep 2012
Posts: 2

PostPosted: Thu Sep 20, 2012 7:24 am    Post subject: Reply with quote

rodneyrehm wrote:
exactly. You have your own error handler which does not respect error_reporting level. You may be doing this on purpose, you may not.

Thank you for this explanation, rodney.

I have no set_error_handler anywhere in my application code and cannot track down where the defualt behavior that Smarty expects is causing the "Warning: filemtime(): stat failed for /path/to/smarty/cache/3ab50a623e65185c49bf17c63c90cc56070ea85c.one.tpl.php
in /path/to/smarty/libs/sysplugins/smarty_resource.php" that OP is experiencing.

I have tried invoking the Smarty::muteExpectedErrors() around where my fetch() is being called by the warning still comes up whenever there is no cache file in the templates_c directory.

Is there some .ini configuration that is setting this off that is incompatible with Smarty::muteExpectedErrors(), or am I missing a step in how Smarty::muteExpectedErrors() is invoked to prevent this issue? (3.1.8 btw)

Thanks!
Back to top
View user's profile Send private message
U.Tews
Administrator


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

PostPosted: Thu Sep 20, 2012 3:49 pm    Post subject: Reply with quote

Note that you must use the $smarty->setTemplateDir(...), $smarty->setCompileDir(...) and $smarty->setCacheDir(...) methods to set up the folders. If you make direct assignments to the properties in the constructor muteExpectedErrors() does not work.
Back to top
View user's profile Send private message
antman
Smarty n00b


Joined: 20 Sep 2012
Posts: 2

PostPosted: Thu Sep 20, 2012 4:39 pm    Post subject: Reply with quote

U.Tews wrote:
Note that you must use the $smarty->setTemplateDir(...), $smarty->setCompileDir(...) and $smarty->setCacheDir(...) methods to set up the folders. If you make direct assignments to the properties in the constructor muteExpectedErrors() does not work.

I'm either a couple steps ahead or behind you.

Without setting these methods my test install reads:

Code:
Smarty Installation test...
Testing template directory...
E:\<path>\templates is OK.
Testing compile directory...
E:\<path>\templates_c is OK.
Testing plugins directory...
E:\<path>\plugins is OK.
Testing cache directory...
E:\<path>\cache is OK.
Testing configs directory...
E:\<path>\configs is OK.
Testing sysplugin files...
... OK
Testing plugin files...
... OK
Tests complete.


With the methods explicitly setting the folders this testInstall() returns the same, however the error that I and OP describe appears on EVERY page load, not just on the "first" time when there is no cache for the file in the cache directory.

So why would my testInstall() be telling me that everything was OK if it was something that wasn't configured right? Do you have any links you could point out for a simpleton how the Smarty::muteExpectedError() works, because either I'm doing something dumb with that or Smarty is just too temperamental for me to use.

And, my template IS displaying the variable I've injected into it ... just with that
Code:
 Warning: filemtime(): stat failed
warning showing in Xdebug driving me nuts.
Back to top
View user's profile Send private message
U.Tews
Administrator


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

PostPosted: Thu Sep 20, 2012 5:35 pm    Post subject: Reply with quote

testInstall() does test if the configured folders have the right permissions that they can be accessed.

muteExpectedErrors() does suppress warnings of internally registered directories. This internal registration process does not work if you set up folder properties by direct assignments within constructor.

Code:
function __construct() {
  $this->compile_dir = 'mypath';  // does not mute
  $this->setCompileDir( 'mypath');  // does mute
}


But as far as I know XDEBUG will grab during debugging notices independent from any error handler setting. This could be your problem.

Our findings have been that filemtime() without calling file_exist() upfront does have better performance.

See also http://blog.rodneyrehm.de/archives/12-Improving-Disk-IO-in-PHP-Apps.html
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Smarty Forum Index -> Bugs All times are GMT
Page 1 of 1

 
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