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

Getting error Invalid compiled template for '...'
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 -> General
View previous topic :: View next topic  
Author Message
jonyo
Smarty Rookie


Joined: 14 Feb 2011
Posts: 16

PostPosted: Thu Jan 12, 2012 11:20 pm    Post subject: Getting error Invalid compiled template for '...' Reply with quote

I am making it so that smarty exceptions are caught, and it sends an e-mail to the admin user for our software application.

After doing this, we've gotten reports of people getting the error in their e-mail but when they go to the page in question it works fine:
Code:
Invalid compiled template for 'footer.tpl'


And YES I did clear the contents of templates_c folder. And a quick google search for "Invalid compiled template for" will show that Google is pretty good at reproducing the error, and it's not just our software so doubt it is something funky we are doing. I think it's just so hard to reproduce that no one sees it happening.

The exception is thrown in file "smarty/sysplugins/smarty_internal_templatebase.php" in line 174. This is in smarty 3.1.5 but I've uploaded 3.1.7 and it still does it.

This is very hard to reproduce, it seems to only happen on high-traffic sites when there are a bunch of concurrent page views (not necessarily exact same page, but sharing same template or sub-templates on pages). I ended up having to go learn how to use JMeter (Software for load testing and web app testing) in order to make it load a ton of page loads concurrently. By making it simulate 100 users all going to the main page, almost every time I run it, it will have at least 1 time that produces the error.

So now that I have a way to reproduce, I started debugging, and found if I change line 161 to use require like so:
Code:
require($_template->compiled->filepath);


NOW the few times it might have thrown an exception, instead it throws a fatal error on line 161 because the resource was not available.

It seems to be some sort of race condition. Interestingly if I make it get the contents of the file it just tried to include using file_get_contents() it is able to retrieve the contents, which backs up it being some weird race condition, or could be problem with file stat being outdated, so it just "thinks" the file is not there, or maybe there is a lock on the file or something.

I don't know enough about how the smarty templates are compiled to know where to go from here. I know a few quick hack solutions that might work (like if the include fails, maybe clear file stat cache and try to include again, even just the extra time that would take might be the time it needs to have the file become available), but I'm sure there is an elegant solution to this, most likely further up in the process of fetching the template.
Back to top
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Fri Jan 13, 2012 1:59 am    Post subject: Reply with quote

That is exactly what it sounds like, a race condition. At the time one thread tries to read a template file (or compile one), another thread has removed it in preparation of a recompile. If many threads are attempting to recompile, this can cause all sorts of erratic behavior (and unnecessary recompile processing.)

We have done a few things to help with this problem, but it is not completely avoidable. With very high traffic sites we can only suggest you do not do "live" template recompilation. The live site should do no compile checking, while an internal site can do manual compile check/recompile to avoid the racing -- even that can cause a race because the live site will still attempt a compile if something is missing, so the best solution is go offline to recompile... which isn't always a practical solution either.

I know there was some internal discussion about aggressive race condition handling, I'll dig up where that ended. I know it's not easy to solve every situation adequately.
Back to top
View user's profile Send private message Visit poster's website
jonyo
Smarty Rookie


Joined: 14 Feb 2011
Posts: 16

PostPosted: Fri Jan 13, 2012 2:49 am    Post subject: Reply with quote

If it is a race condition, one question I have is why would something need to recompile the template? I thought once something was compiled, as long as the Smarty template engine is not updated, it doesn't need to be re-compiled after that?

I ask because the templates this error tends to happen on, are ones that are used on every page like footer.tpl or header.tpl, templates that should have already been compiled from previous page loads. That's the part where I mentioned I don't know enough about how the Smarty compilation works anymore to be able to come up with the "best" or most elegant solution, since I'm not sure why it is needing to re-compile it in the first place.
Back to top
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Fri Jan 13, 2012 4:26 am    Post subject: Reply with quote

Oh, I assumed you meant you change templates on occasion, and that would be when an error would show up. Smarty does not have to recompile if the source templates don't change. Smarty does however, check if a template needs compiling on each invocation by default. You are best off disabling compile_check with heavy traffic sites, that will skip a somewhat expensive and unnecessary step. See if that helps with the errors too. I'm not exactly sure why those would pop up. For whatever reason, PHP is having trouble reading those files in some circumstance of your environment.
Back to top
View user's profile Send private message Visit poster's website
jonyo
Smarty Rookie


Joined: 14 Feb 2011
Posts: 16

PostPosted: Fri Jan 13, 2012 4:59 pm    Post subject: Reply with quote

mohrt wrote:
Oh, I assumed you meant you change templates on occasion, and that would be when an error would show up. Smarty does not have to recompile if the source templates don't change. Smarty does however, check if a template needs compiling on each invocation by default. You are best off disabling compile_check with heavy traffic sites, that will skip a somewhat expensive and unnecessary step. See if that helps with the errors too. I'm not exactly sure why those would pop up. For whatever reason, PHP is having trouble reading those files in some circumstance of your environment.


No changes to the template files. I'll focus on a single template here for simplicity, but this is happening on other template files as well...

When I look at the footer.tpl template file itself (uncompiled version), it shows it was last changed July 1, 2010.

Looking at the compiled file, it has a timestamp from a minute ago. If I refresh viewing one of the pages the footer.tpl file is used on, after a few page views the timestamp on the compiled template changes. I double check the timestamp on the original footer.tpl and it's still July 1 2010, still exact same size, no changes at all.

Any ideas what could be causing it to do a force recompile of the template every few page loads?
Back to top
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Fri Jan 13, 2012 5:04 pm    Post subject: Reply with quote

Smarty compares the file times of the source files with the compiled files, and recompiles if the source is newer. is anything touching the source files? is there any sort of error or fluctuation with your system time clock?

double check the setting of the template_dir, compile_dir, clear out all your compiled/cached files. make sure you are using the latest Smarty of the major version number.
Back to top
View user's profile Send private message Visit poster's website
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Fri Jan 13, 2012 5:13 pm    Post subject: Reply with quote

Do you have compile_check disabled? (you should anyways)
Back to top
View user's profile Send private message Visit poster's website
jonyo
Smarty Rookie


Joined: 14 Feb 2011
Posts: 16

PostPosted: Fri Jan 13, 2012 5:50 pm    Post subject: Reply with quote

mohrt wrote:
Smarty compares the file times of the source files with the compiled files, and recompiles if the source is newer. is anything touching the source files? is there any sort of error or fluctuation with your system time clock?

double check the setting of the template_dir, compile_dir, clear out all your compiled/cached files. make sure you are using the latest Smarty of the major version number.


Nothing is touching the source files, sorry if I wasn't clear earlier, I was referring to the source file when I said it had a timestamp of July 1 2010, and that does not change.

And I doubt there is an error/fluctuation with system time clock, or if there is it is a problem shared by a lot of our clients as well.

The template_dir and compile_dir are set to what they have always been, if those were incorrect wouldn't it result in it not working at all?

And I've updated to 3.1.7, and cleared out templates_c (again).

No I do not have compile_check disabled. I suppose I could set that to false and see if problem still happens, if it does not happen any more it is something related to timestamp.

I'm going to try a few more debug ideas I have to see if I can track down "why" it is deciding to do a recompile then we can go from there.

Also, thanks for your help so far on this Smile
Back to top
View user's profile Send private message
jonyo
Smarty Rookie


Joined: 14 Feb 2011
Posts: 16

PostPosted: Fri Jan 13, 2012 7:10 pm    Post subject: Reply with quote

Doh! Did a debug_backtrace() on the method that writes the compiled template, and it is because we are using $smarty->getTags().

Apparently getTags() will always compile the template no matter what, are the tags on a template only "known" if the compiled template is being compiled at that time? In other words is this intentional, is there no other way to get the tags used on a template other than re-compiling it every time?

I'll play around with it and see if I can figure out a way to get it to work without re-compiling the template every time.
Back to top
View user's profile Send private message
jonyo
Smarty Rookie


Joined: 14 Feb 2011
Posts: 16

PostPosted: Fri Jan 13, 2012 7:43 pm    Post subject: Reply with quote

OK so turns out like I said getTags will compile the template, and that is because it keeps track of what tags are used by adding to an array in the compileTag() method.

Think it would be possible to make it so that if $template->tags_used is populated, it sets that info in the properties of the compiled template? So if $smarty->get_used_tags is true, it keeps track of the tags used during compilation, then also saves those tags in the compiled template parameters that is part of the compiled template... Doing that should not affect performance, since it would only be done if $smarty->get_used_tags is true.

Although, I don't like that solution either. I really didn't like the solution I did come up with, parsing through the used tags (even if it did NOT result in re-compile, obviously it is not ideal as that is a lot of extra overhead). Does anyone have a way we can accomplish the following the "best" way?

end result:

This is super-simplifed for demonstration purposes...

Code:

<html>
<head>
{custom_insert_head}
<title>...</title>
...
</head>
<body>
...
{custom_module name='module1'}
...
{custom_module name='module2'}
</body>
</html>


Given that example, the 2 {custom_module ...} tags insert some fancy stuff on the page. As part of that, it needs to insert some extra JS and CSS into the <head> section, as part of the output of {custom_insert_head}.

So any suggestions on the best, most efficient way to accomplish this? And I'm talking at the code level, we already have a custom resource, custom smarty functions, and use of our own class that extends the smarty class, so not afraid to get hands dirty at the code level (short of modding the smarty core files, unless said mods happen to be something to be added in future version of smarty).
Back to top
View user's profile Send private message
jonyo
Smarty Rookie


Joined: 14 Feb 2011
Posts: 16

PostPosted: Mon Jan 23, 2012 7:58 pm    Post subject: Reply with quote

Just wanted to update, I was able to find a solution to do what I needed without using getTags(). But my use of getTags only highlighted the problem originally posted, for high-traffic sites there is a "common" race condition that can happen when another page-load is re-writing the same compiled file at almost same time.

A simple search for the error will reveal that this is happening for sites. One scenario in particular, is when a search robot is indexing or re-indexing pages on your site, it could reproduce the issue if it happens to go to pages that are not used very often and not compiled yet, then it ends up with pages on the site indexed with the error (like all the pages that come up when you do that search).

If it was a complex problem to fix I would agree it may not be worth addressing, just accepting that race conditions will always be possible, but in this case the fix is easy: if the inclusion of the compiled file fails, sleep for a tenth of a second or so then try again, maybe try it up to 3 times or something before giving up. Sure it is a rare problem and can easily be avoided by compiling all templates on a production site, but I would argue that BECAUSE it is so rare, and is so hard to see the error, it would result in search engine indexing the error on pages on a site and the site owner would never know, since going to the page in question does not pull up the error "after the fact", that is more reason to fix it rather than tell people a work around. Most that have this problem wouldn't know they had it, so would not know they needed to possibly seek a work around...
Back to top
View user's profile Send private message
U.Tews
Administrator


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

PostPosted: Mon Jan 23, 2012 11:16 pm    Post subject: Reply with quote

Smarty3 does prevent concurrent compilations of same template when a template was updated.

I your case concurrent compilations have been forced by getTags() calls in production scripts which was not intended when proviging this function.

I will revisit the code to check if we could run into race conditions when a compiled template did not exists.
Back to top
View user's profile Send private message
jonyo
Smarty Rookie


Joined: 14 Feb 2011
Posts: 16

PostPosted: Tue Jan 24, 2012 3:54 am    Post subject: Reply with quote

U.Tews wrote:
Smarty3 does prevent concurrent compilations of same template when a template was updated.

I your case concurrent compilations have been forced by getTags() calls in production scripts which was not intended when proviging this function.

I will revisit the code to check if we could run into race conditions when a compiled template did not exists.


Good point, it would require both pages to be trying to re-compile an already compiled page. I think that can happen though when a compiled template uses an older version of smarty, something like this:

1. page view a: needs to compile template, sees that template is using old smarty version.
2. page view b: needs to compile template, sees that template is using old smarty version.
3. page a: deletes template, and re-writes.
4. page b: deletes template (in preparation for write)
5. page a: attempt to include template that was just written, fails because of deletion by page view b. Currently, it just throws error and gives up basically via error reported in first post.
6. page b: writes re-generated compiled template contents.

I haven't done a "full" code review so not entirely sure the above race condition is possible, it's just theory based on the knowledge that it is possible to get into race condition when it re-compiles templates with every page load. I believe the above scenario would "mimic" that close enough to be possible.
Back to top
View user's profile Send private message
U.Tews
Administrator


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

PostPosted: Tue Jan 24, 2012 7:48 pm    Post subject: Reply with quote

This condition is interlocked.

Anyway I will recheck the different conditions of concurrent compilation requests.
Back to top
View user's profile Send private message
ikund
Smarty Rookie


Joined: 22 Nov 2011
Posts: 9

PostPosted: Mon Jun 18, 2012 1:25 pm    Post subject: Reply with quote

Hi,

I'm getting the same exceptions on another high-traffic site. Exceptions pop up even if nobody is updating any templates, the timestamp for cache files is not updated (which would normally cause the recompile). The problem involves (mostly) templates that are used more (banner boxes etc).

However, I am not using getTags. Any ideas? Oh and the exceptions started appearing after Smarty upgrade from 3.1.5 to 3.1.10.

Thanks, I would really appreciate help with this matter.
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 -> General 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