After upgrading to the latest dev version sites stopped loading.
The reason is the infinite loop in _rules_discover_module():
...
$file_path = str_replace(DRUPAL_ROOT . '/', '', $reflection->getFileName());
while (!isset($paths[$file_path]) && strpos($file_path, DIRECTORY_SEPARATOR) !== FALSE) {
$file_path = dirname($file_path);
}
Link: http://drupalcode.org/project/rules.git/blob/HEAD:/rules.module#l290
Halting conditions triggers when for example you have a Rules module directory as a symbolic link. In this case $reflection->getFileName() returns real path, and str_replace() doesn't replaces anything, and then the loop body $file_path = dirname($file_path); reaches "/" path and gets into inftinite iteration.
This should be fixed to
1) support symbolic links
2) not produce halting problem
Comments
Comment #1
OnkelTem commentedMy symlinking story:
Comment #2
fagowow :-)
So, could you check what's the value of
and
drupal_get_path('module', 'rules')is for you?
At least it looks like the bail-out condition
strpos($file_path, DIRECTORY_SEPARATOR) !== FALSEdoes not work, so we need to come up with something better here. e.g., just remove any slashes from the beginning?Comment #3
OnkelTem commentedFor the initial conditions when:
/var/www/lib/d7_dev/extensions/modules/rules/rules.module/var/www/sites/example.com/sites/~all -> /var/www/lib/d7_dev/extensions/$classbeen passed to the function is'RulesNodeConditionType'DRUPAL_ROOTequals to/var/www/sites/example.comwe get:
'sites/all/modules/rules' => 'rules'/var/www/lib/d7_dev/extensions/modules/rules/modules/node.eval.inc$file_path = str_replace(DRUPAL_ROOT . '/', '', $reflection->getFileName());returns just the same:/var/www/lib/d7_dev/extensions/modules/rules/modules/node.eval.incdrupal_get_path('module', 'rules')is obviously:sites/all/modules/rulesComment #4
OnkelTem commentedfago, I personally don't see any simple solution. Basically the task is in restoring original file structure for any files tree containing symlinks.
I could have for example:
/var/www/sites/example.com/sites/all/modules/rulesas a real dir, while having:/var/www/sites/example.com/sites/all/modules/rules/modules/@node.eval.incas a symlink to another location, which is also a symlink to one more location, which is finally the symlink the Moon.So you have to walk through the files, down (as a $class could be defined anywhere), testing is it a link, resolving each, recursively until you real the real file, and then walk up, finding it's place in the hierarchy of modules.
How to disable this part and rollback to the previous behavior?
Comment #5
OnkelTem commentedCan't we simply use
{registry}table?Comment #6
socialnicheguru commentedI tried the above change but my system did hang.
I had to revert to a previous version of rules.
I am using symlinks to link needed modules from a central directory
Comment #7
das-peter commentedAnother evil case: Windows
Because the directory separator is a back-slash rather than a slash the
str_replace()function can't clean the file path either.Attached patch changes
. '/'to. DIRECTORY_SEPARATORwhich will provide the OS specific directory separator.Also there's this issue that looks related: #2060713: Maximum time exceeded: internal loop in _rules_discover_module if called with a class whose path cannot be found
Comment #8
plachWhat about this? It should correctly handle absolute paths, windows separators and avoid infinite loops.
Comment #9
das-peter commentedI like the approach and I think that should solve the issue. However, I just did a visual review for now.
Not sure if we need the condition here. Without I'd say it's more readable but it could affect the performance,?
Comment #10
plachWell, it was just micro-optimization, I guess we can skip it if we prefer readability :)
Comment #11
stefan.kornFor me the patch from #8 works. I had the problem (Max execution time exceeded in rules.module) after transfering a drupal instance from Linux to Windows.
Comment #12
das-peter commentedI'm bold enough to say RTBC then as of #11.
Comment #13
fagoThanks folks - committed!
Comment #14.0
(not verified) commentedasd as always