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

Endless loop while trying to compile a template
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
Mastershrimp
Smarty Regular


Joined: 21 Dec 2009
Posts: 53

PostPosted: Tue Oct 04, 2011 8:05 pm    Post subject: Endless loop while trying to compile a template Reply with quote

Hi,

I'm afraid but I think that topic is gonna last a while - at least the problem seems really random to me. I can hardly reproduce it at all. Anyways. I'll dive right into it:

Scenario:
In the past weeks I primarily developed on my local machine (Win7, PHP5.2.8 on an XAMPP). Therefore I updated Smarty (3.0 -> 3.1) only locally at first. That worked more or less smoothly and in the end I got it running successfully.

Now I decided to update a semi-productive system with the so-far working state from my local machine. And that's when the fun began.

You know, I use Smarty for all backend files. So, I was able to open the index page of the backend (very simple template). However, opening another more complex backend page (that includes another template using {include file="filename.tpl"}) crashed Smarty. All I could see was the (correct) content of my header.tpl and then some weird var_dump-like output of the Smarty object instead of the content of my index.tpl (the body of the page). And that output was gigantic! Maybe it's even an endless loop - I dont know. My browser was about to crash, so I hit "stop".

Then I started to narrow down the problem. I deleted everything in the outer template except {include file="filename.tpl"} (relative path, both templates are in the same folder). And I deleted everything in the inner template except "hello world". The weird var_dump-output was still there.

Then I began to remove the $smarty->assign()'s in the original .php-file. I was able to remove all assignments that dealt with simple values (strings, numbers, booleans) while keeping the error. So, what was left was 1 assignment of a quite large array of objects. After removing the assignment of this array, the templates were displayed correctly.

Then I restored the deleted code in all files (the php and the 2 templates) - and against all odds, everything was working fine!

Then I deleted the contents of templates_c and everything was back to "normal" (i.e. the error with the var_dump-output came back).


My guess
Therefore my guess is that Smarty is somehow unable to compile the templates when there is a {include} in the template's code. I observed a similar behavior as described above in other templates (that also included other templates). So maybe you could have a look at compiling {include}'s?


As I said, it's really hard to reproduce and I'm far from being able to provide sample code. But maybe I described the problem in sufficient detail, so you can still have a look at the piece code that might be the culprit.

That'd be great! Because the bug somehow puts me in a delicate position (I could revert to 3.0 but then I wouldnt be able to receive any updates of Smarty anymore...)

Best regards


PS: In the meantime I tried the very latest revision from the SVN (rev4354). Without success. Sad


PPS: I just want to stress that it seems to be sufficient to remove the assign() of the big array in order to make the templates work.
In case of an error, the compiled template for the index.tpl is not generated fully. Instead, I find a file called "wrt4e8b6948e7a31" in templates_c.
After removing the assign of the array, the template is compiled correctly (now named "...some characters....file.index.tpl.php").

The content of the two generated files is almost the same, except for some random-character-strings in the head of the files (e.g. in "'unifunc' => 'content_4e8b6948e5aeb'").

In case it helps I uploaded a zip containing both compiled files (the correct and the broken one): http://www57.zippyshare.com/v/79871858/file.html I have sent the PW for the zip to u.tews via PM - I hope that's ok Smile
Back to top
View user's profile Send private message
Mastershrimp
Smarty Regular


Joined: 21 Dec 2009
Posts: 53

PostPosted: Wed Oct 05, 2011 8:20 am    Post subject: Reply with quote

Good morning Smile

still working on narrowing down the problem. Now I think {include} is not important. At least I was able to reproduce the error with just 1 template containing "bla". So it's not about the template.

So, basically the browser crashes because somehow the Smarty object is var_dump'ed while compiling the template. And since the Smarty object has got that huge array, the var_dump takes forever (or is actually endless). The array is huge because it contains objects that have properties that contain objects themselves that contain....and so on, you know Wink There are actually also some recursions within that structure (var_dump prints "RECURSION"), so it's really big and definitely not var_dump'able Very Happy

I am really wondering why the Smarty object is printed at all. Did you change something like that in 3.1.x? 3.0 was fine, as I said.

Maybe something with the output buffer (ob_start/ob_get)?
Or some left developer debug output?

The weird thing is, that locally it works perfectly. Btw, the server is running Apache/2.2.3 (Debian) PHP/5.2.8-0.dotdeb.1 with Suhosin-Patch. I'm not sure, but I vaguely remember some problems with the Suhosin patch (with some other scripts). So maybe there is a problem with Smarty and that patch? Do you have such an environment that you could use for testing purposes?
Back to top
View user's profile Send private message
Mastershrimp
Smarty Regular


Joined: 21 Dec 2009
Posts: 53

PostPosted: Wed Oct 05, 2011 8:44 am    Post subject: Reply with quote

Sorry for posting again, just wanna keep you up2date Wink

I significantly reduced the number of objects in the array (by deleting contents in the DB). Now I get
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 103574794 bytes) in /var/...my path.../inc/globalFunctions.inc.php on line 31

That line is one of my own escape methods
Code:
function out($content, $placeholderContent=null) {
   // --- Insert placeholders if given
   if(count(func_get_args())>2 || !empty($placeholderContent)) {
      $functionArguments   = func_get_args();
      $content         = call_user_func_array("sprintf", $functionArguments);
   }

   // htmlspecialchars cannot handle arrays -> replace with indicator that an array has been provided to this method
   if(is_array($content))
      $content = "[array provided]";

   // Encode html relevant characters
   return htmlspecialchars($content, ENT_QUOTES, "UTF-8");
}


This function is also registered as modifier "out" (for {$myVar|out}).

So I var_dump'ed $content in this function to see when it's called with what parameters. Surprisingly, it was called a lot! It seemed like it is processing also Smarty properties and objects....dont know.

Maybe there is a name collision? Did you introduce a function called "out" recently? That would explain why the Smarty object is being printed at all...
Back to top
View user's profile Send private message
rodneyrehm
Administrator


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

PostPosted: Wed Oct 05, 2011 2:47 pm    Post subject: Reply with quote

just a hunch: please check your ->assign() calls and make sure their return values are not processed in any way. For a quicker test, comment out all "return $this;" in Smarty_Internal_Templatebase.php
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
Mastershrimp
Smarty Regular


Joined: 21 Dec 2009
Posts: 53

PostPosted: Wed Oct 05, 2011 3:05 pm    Post subject: Reply with quote

Thanks! Smile

But I'm not aware of using the return value of $smarty->assign()....didnt even know that it would make sense at some point. I quickly checked my code with a regex and it seems I'm using it only like "$smarty->assign(...)".

However I'd still like to do your quick test. However I couldnt find any "return $this;" in smarty_internal_templatebase.php. Only stuff like "return $this->$property_name;" and so on.

Could you give me a line number so I can see what you mean?

In case that doesnt help, do you have another idea? I'm willing to try basically anything - I really need this fixed, you know Wink
Back to top
View user's profile Send private message
Mastershrimp
Smarty Regular


Joined: 21 Dec 2009
Posts: 53

PostPosted: Wed Oct 05, 2011 3:11 pm    Post subject: Reply with quote

Not sure if it helps, but I actually dont use Smarty directly but rather as an extended sub-class "MySmarty". Maybe I'm using it the wrong way?

This is the constructor of the class:
Code:
/**
 * Constructor of MySmarty
 *
 * This method also tries to set the $template_dir by considering $templateDir. Templates referenced by a relative path have to be in that directory.
 * If not set the templates have to be referenced by absolute paths.
 *
 * You can also fetch files outside of $template_dir (e.g. in case you don't want to specify $module) using display("file: ....myfile.ext").
 * See http://www.smarty.net/manual/en/template.resources.php for more details.
 *
 * @param string|Folder $templateDir The path to the folder of the templates. If not provided, only templates referenced by absolute paths can be fetched
 */
public function __construct($templateDir=null) {
   parent::__construct();

   // Smarty settings
   $this->setForceCompile(false);                  // See http://www.smarty.net/manual/en/variable.force.compile.php
   $this->setCompileCheck(Smarty::COMPILECHECK_ON);   // See http://www.smarty.net/manual/en/variable.compile.check.php
   $this->setDebugging(false);                     // If true, shows a JS popup debug console
   $this->error_reporting = E_ALL ^ E_NOTICE;         // Report all errors except E_NOTICE (e.g. thrown for undefined template tags)

   // Directories (no exceptions because exceptions might be displayed using a template, too)
   $this->setCompileDir(EXTERNAL_LIBS_PATH . "smarty" . DIRECTORY_SEPARATOR . "templates_c");
   if(!is_writeable($this->getCompileDir())) {
      echo "Smarty: compile_dir not writeable: " . out($this->getCompileDir());
      exit;
   }
   $this->setConfigDir(EXTERNAL_LIBS_PATH . "smarty" . DIRECTORY_SEPARATOR . "configs");
   if(!is_writeable($this->getConfigDir(0))) {
      echo "Smarty: compile_dir not writeable: " . out($this->getConfigDir(0));
      exit;
   }
   $this->setCacheDir(EXTERNAL_LIBS_PATH . "smarty" . DIRECTORY_SEPARATOR . "cache");
   if(!is_writeable($this->getCacheDir())) {
      echo "Smarty: compile_dir not writeable: " . out($this->getCacheDir());
      exit;
   }

   // Look for template directory
   if($templateDir!==null) {
      if($templateDir instanceof Folder)
         $templateDir = $templateDir->getPath();

      // Check directory (no exceptions because exceptions might be displayed using a template, too)
      if(!file_exists($templateDir)) {
         echo "Smarty: Current template_dir does not exist: " . out($templateDir);
         exit;
      }
      elseif(!is_readable($templateDir)) {
         echo "Smarty: Current template_dir not readable: " . out($templateDir);
         exit;
      }
      else
         $this->setTemplateDir($templateDir);
   }

   // Register own modifiers
   $this->registerPlugin("modifier", "out", "out");
   $this->registerPlugin("modifier", "outHTML", "outHTML");
   $this->registerPlugin("modifier", "info", array("Tools", "info"));
   $this->registerPlugin("modifier", "absolutizeImgSrc", array("Tools", "absolutizeImgSrc"));

   // Assign default variables
   $this->assignDefaultTplVars();
}


/**
 * Assigns some default template variables that should be available in all templates
 *
 * @return MySmarty Returns the current object
 */
public function assignDefaultTplVars() {
   // Register the $myAccount object
   $this->assign("myAccount", Account::getMyAccountObject());

   // Workaround since Smarty doesnt support static calls (yet)
   $this->assign("serverInstallationCompleted", ServerCheck::installationCompleted());

   //Assign current skins dir as Smarty var
   $this->assign("frontendSkinWebPath", Skin::getFrontendSkin()->getWebPath());
   $this->assign("backendSkinWebPath", Skin::getBackendSkin()->getWebPath());

   return $this;
}
Back to top
View user's profile Send private message
U.Tews
Administrator


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

PostPosted: Wed Oct 05, 2011 3:37 pm    Post subject: Reply with quote

Globe
Quote:
just a hunch: please check your ->assign() calls and make sure their return values are not processed in any way. For a quicker test, comment out all "return $this;" in Smarty_Internal_Templatebase.php


Should have been:
comment out all "return $this;" in Smarty_Internal_Data.php

Before you then retry delete all existing files in the cache_dir and compile_dir folder.
Back to top
View user's profile Send private message
rodneyrehm
Administrator


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

PostPosted: Wed Oct 05, 2011 3:54 pm    Post subject: Reply with quote

See? I told ya I needed to eat before getting back to Smarty! Wink
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
Mastershrimp
Smarty Regular


Joined: 21 Dec 2009
Posts: 53

PostPosted: Wed Oct 05, 2011 4:05 pm    Post subject: Reply with quote

Haha, no hurry Wink

But I'm sorry, the error remains. I cleared templates_c.
Back to top
View user's profile Send private message
rodneyrehm
Administrator


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

PostPosted: Wed Oct 05, 2011 4:23 pm    Post subject: Reply with quote

have you removed "return $this;" from Smarty_Internal_Data.php?
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
Mastershrimp
Smarty Regular


Joined: 21 Dec 2009
Posts: 53

PostPosted: Wed Oct 05, 2011 4:43 pm    Post subject: Reply with quote

Yes, sure. Commented all "return $this"'s out. Then cleared templates_c and hit reload. Same thing.

Edit: Also removed the "return (string) $this" from Smarty_Variable::__toString().
Back to top
View user's profile Send private message
Mastershrimp
Smarty Regular


Joined: 21 Dec 2009
Posts: 53

PostPosted: Thu Oct 06, 2011 10:19 am    Post subject: Reply with quote

So, do you have any idea how to fix it? So far the only option I have is downgrading Smarty to 3.0x....but that cannot be it I guess :/
Back to top
View user's profile Send private message
rodneyrehm
Administrator


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

PostPosted: Thu Oct 06, 2011 10:29 am    Post subject: Reply with quote

can you identify where that memory limit exceeded error is happening? (Stack trace or something?)
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
Mastershrimp
Smarty Regular


Joined: 21 Dec 2009
Posts: 53

PostPosted: Thu Oct 06, 2011 10:34 am    Post subject: Reply with quote

Yeah, kinda at least. During my experiments with different templates I saw that the memory limit exceeded in one of my output functions. I use them all the time to mask HTML and so on. I also registered them as modifier. But as I said earlier, I reproduced the error just with a template containing "hello world" (no code, no modifiers, no nothing). So it's not about the template I guess. Rather sth with the compiling or so....no idea.

The affected function was:
Code:
function out($content, $placeholderContent=null) {
   // --- Insert placeholders if given
   if($placeholderContent !== null && count(func_get_args())>=2) {
      $functionArguments   = func_get_args();
      $content         = call_user_func_array("sprintf", $functionArguments);
   }

   // htmlspecialchars cannot handle arrays -> replace with indicator that an array has been provided to this method
   if(is_array($content))
      $content = "[array provided]";

   // Encode html relevant characters
   return htmlspecialchars($content, ENT_QUOTES, "UTF-8");
}


The last line (return htmlspecialchars($content, ENT_QUOTES, "UTF-8");) is the one where the memory limit exceeded last time I saw the error message.

It's really weird. Some templates have that giant output (mentioned above) so I cancel the loading of the page. Other templates terminate quickly with "Memory limit exceeded" at that line mentioned above.

I really cannot figure out the cause. It seems very deep down in the code...Maybe something about the changes regarding the UTF8-compatibility of Smarty?


Edit: When I figured out that "out()" is causing problems, I var_dump'ed $content and looked at the result. Somehow the Smarty object ended up being printed (among other stuff of course)....so again, somehow Smarty is being printed (leading to the giant output in the one case and the memory limit in the other)
Back to top
View user's profile Send private message
rodneyrehm
Administrator


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

PostPosted: Thu Oct 06, 2011 10:43 am    Post subject: Reply with quote

well, I'm pretty sure this is not a compiler-problem. This has got to do with the data you've assign()ed. did you throw the $smarty object into the assign()ed array?
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
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