Fatal error: Call to undefined function: drupal_goto()

kmillecam - December 11, 2007 - 23:48
Project:Path redirect
Version:5.x-1.x-dev
Component:Code
Category:bug report
Priority:critical
Assigned:Unassigned
Status:closed
Description

Hi all,

I installed Path Redirect about a week ago on my site and today, out of the blue, anonymous users (caching is enabled) started getting this error:

Fatal error: Call to undefined function: drupal_goto() in /home/juice00/public_html/sites/all/modules/contrib/path_redirect/path_redirect.module on line 34

Authenticated users did not get the error.

I used Devel to clear the server cache but that didn't seem to help.
I then disabled path_redirect and cleared the cache again and the problem disappeared.

I love this module and want to continue using it so whatever I can do to help troubleshoot this problem ... I'm ready to help.

The site gets about 10,000 page views a day so it's moderately active.

TIA,
Kevin

#1

jjeff - December 12, 2007 - 02:13

Fascinating.

Okay, my hypothesis is that you've got page caching enabled for anonymous users. And because of this, Drupal isn't doing enough of a bootstrap to load the drupal_goto().

I'll bet we should do something along the lines of

<?php

if (function_exists('drupal_goto')) {
 
// the normal drupal_goto() statement
}
else {
 
// we do our own redirect
}
?>

#2

jjeff - December 12, 2007 - 02:17

...just so I've asked...

on the admin/settings/performance page, you have "Caching mode" set to "Normal" (and not "Aggressive"), right?

You'll be able to alleviate the immediate Fatal Error problem by turning "Caching mode" to "Disabled", by the way.

#3

kmillecam - December 12, 2007 - 04:21

Thanks Jeff,

Yeah, page caching was on (Normal, not Advanced).

I appreciate you taking a look at this.

Kevin

#4

kmillecam - December 12, 2007 - 21:55

Where you thinking about something along these lines?

<?php
if (function_exists('drupal_goto')) {
 
drupal_goto($r->redirect, ($r->query ? $r->query: NULL), ($r->fragment ? $r->fragment : NULL), $r->type);
}
else {
 
header("Location: $r->redirect");
}
?>

Kevin

#5

HorsePunchKid - December 16, 2007 - 14:21

Do we need a warning somewhere in the admin interface to explain this to users?

#6

jjeff - December 16, 2007 - 15:43

Yes. Pretty much, but I think we can put the redirect code, query, fragment, and redirect type into the non-drupal_goto() version.

#7

jjeff - December 16, 2007 - 15:44

Do we need a warning somewhere in the admin interface to explain this to users?

I don't know why we'd need to put a warning in. What would the warning say?

#8

HorsePunchKid - December 16, 2007 - 19:19
Status:active» needs work

Nix that; as long as it works the same way as drupal_goto there is no need for a warning. Here is a patch that doesn't work. Let's say I've got a redirect from foo/bar to baz/quux. This patch (based on kmillecam's suggestion) will send a location header:

Location: baz/quux?query_string#fragment

Looks okay at first, but that's actually going to be treated as relative to the original path foo/bar, resulting in a request for foo/baz/quux?q#f.

So what's the best way to make $r->redirect be relative to the root? Is it safe to call url($r->redirect,...), or is that just as bad as calling drupal_goto?

Should we wrap this in a path_redirect_goto function?

AttachmentSize
path_redirect-5.x-1.x_goto_8.patch 748 bytes

#9

jjeff - December 17, 2007 - 13:55

No, we basically just copy the drupal_goto() function into our module. We could even call it path_redirect_goto(). We can slim it down by removing the 'destination' code (the first few lines of the function.

http://api.drupal.org/api/function/drupal_goto/5

The main question that I've got is: if drupal_goto() hasn't been bootstrapped, then I'm guessing most other stuff hasn't been bootstrapped. The function attempts to run module_invoke_all('exit', $url); and I'm guessing that will bomb out too.

We should try to a) look at the bootstrap process and figure out if the modules are loaded enough to run invoke the 'exit' hooks when (not aggressive) page caching is enabled, or b) just drop the code in and see if we get an error! :-)

There are clues here:
http://api.drupal.org/api/function/bootstrap_hooks/5
and here
http://api.drupal.org/api/function/_drupal_cache_init/5

Hmmm... interesting... from _drupal_cache_init():

<?php
elseif (variable_get('cache', CACHE_DISABLED) == CACHE_NORMAL) {
        require_once
'./includes/module.inc';
       
bootstrap_invoke_all('init');
       
drupal_page_cache_header($cache);
       
bootstrap_invoke_all('exit');
        exit();
      }
?>

It looks like the thing to do is to change drupal_goto()'s module_invoke_all('exit') to bootstrap_invoke_all('exit');

I'll whip up a patch for this as soon as I can.

#10

jjeff - December 17, 2007 - 14:29

Okay here's a patch that I've tested and it's working with page caching. I'm going to commit it.

The patch adds a new function called path_redirect_goto(). This function gets called when drupal_goto() is unavailable.

(it also cleans up some extra spaces at the end of lines)

AttachmentSize
path_redirect_goto.patch 9.2 KB

#11

kmillecam - December 17, 2007 - 20:23

Thanks Jeff!

I'll give it a spin.

Kevin

#12

jjeff - December 17, 2007 - 21:38
Status:needs work» fixed

Committed to dev version.

#13

kmillecam - December 18, 2007 - 21:38
Status:fixed» active

After installing the latest dev version, I'm getting another error:

Fatal error: Call to undefined function: url() in /home/juice00/public_html/sites/all/modules/contrib/path_redirect/path_redirect.module on line 374

#14

HorsePunchKid - December 18, 2007 - 22:24

I think this is what I was worried about in #8 above. It looks like path_redirect_goto() relies on url(), and I think if you don't have drupal_goto(), you're not going to have url(), either. Sorry, I can't offer a patch at the moment.

#15

kmillecam - December 19, 2007 - 03:32

Just wondering ... if we can't depend on Drupal functions loading, could we capture the base url when path_redirect is installed (or as part of the configuration settings)?

Then if drupal_goto() isn't available, it can fall back on the url from the settings.

Kevin

#16

HorsePunchKid - December 23, 2007 - 20:54

I can't seem to reproduce the problem, but perhaps something like this will solve it. Maybe this is too simplistic, though; url() is some 70 lines of code...

AttachmentSize
path_redirect-5.x-1.x_goto_16.patch 684 bytes

#17

HorsePunchKid - December 23, 2007 - 21:58
Status:active» needs work

Status changed.

#18

HorsePunchKid - December 24, 2007 - 19:14
Status:needs work» needs review

I had to mangle a bunch of core files to simulate not having drupal_goto() and url() available, but once I managed that, this patch worked fine. Tested it with relative and absolute URLs, with and without query strings and fragments.

I'd love to get 1.1 out the door once this is fixed!

AttachmentSize
path_redirect-5.x-1.x_goto_18.patch 701 bytes

#19

HorsePunchKid - December 27, 2007 - 05:52
Status:needs review» fixed

Committed #18. I'll consider this fixed, but please reopen if further testing reveals problems!

#20

kmillecam - December 27, 2007 - 21:09

Thanks HorsePunchKid,

I'll load the latest up and give it a try.

Kevin

#21

kmillecam - January 5, 2008 - 05:33

I've been running this version on a couple of production servers for about a week now. Everything looks good.

Thanks for the work guys.

#22

Anonymous - January 19, 2008 - 05:43
Status:fixed» closed

Automatically closed -- issue fixed for two weeks with no activity.

#23

moshe weitzman - May 1, 2008 - 00:28

I think this has been biting us at groups.drupal.org for some time now. I finally dug deep enough to find this error message and see the module has been fixed. Could we please issue a release soon? This was fixed in December.

#24

moshe weitzman - May 2, 2008 - 02:55
Priority:normal» critical
Status:closed» active

This is not fully fixed. This init hook is still calling url() even though common.inc is not loaded. See this clause

url($r->redirect) != url($path)

The error that results in my install is

02-May-2008 02:32:46] PHP Fatal error: Call to undefined function url() in /var/www/groups.drupal.org/htdocs/sites/all/modules/path_redirect/path_redirect.module on line 45

#25

moshe weitzman - May 2, 2008 - 03:21
Status:active» needs review

what about moving all this code to hook_menu(!$may_cache). is a slight performance hit but at least we are all bootstrapped. this is exactly what the D6 version has chosen to do by implementing hook_init() versus the new hook_boot(). hook_boot() is the one that happens during the bootstrap. hook_init() always runs after full bootstrap in D6.

attached is a patch which implements this and gets rid of our workaround code for hook_init(). this is now running on groups.drupal.org.

AttachmentSize
mw.patch 3.58 KB

#26

HorsePunchKid - May 14, 2008 - 01:21
Assigned to:Anonymous» HorsePunchKid

Excellent; thank you for digging into this issue. I'll test the patch. We've gotta get this fixed in the next release (1.3).

#27

hass - May 31, 2008 - 17:42

I checked this patch and some of the above comments... and I'd like to say some things about this change. I learned in global_redirect that hook_init does not provide what you need at this early stage. You need url(), drupal_goto() and some other core functions only available at a later bootstrap. Therefor this should be kept in hook_menu in D5 and in D6 moved to hook_init. hook_init have all functions you need in D6, but not in D5 :-(. It's not optimal, but it works as it should.

I also thought about including all core files and duplicating functions and so on... but there are so many dependencies in path.inc that you will end up with much code and the benefit of duplicating the functions seems no more appropriate.

#28

TallDavid - November 3, 2008 - 16:54

Fatal error: Call to undefined function url() in ... path_redirect.module on line 45

5.x-1.2 (Latest 5/14/2008 release version) is still suffering from this problem. Any chance of getting a fix into a release in the near term?

#29

DamienMcKenna - January 27, 2009 - 04:35

Agreement on it needing to be resolved, am experiencing this quite a bit.

Has anyone tried the change suggested by skcombs?
http://drupal.org/node/290221#comment-1155822

#30

Dave Reid - January 27, 2009 - 19:57
Assigned to:HorsePunchKid» Anonymous
Status:needs review» fixed

I've had a fun time with the hook_menu(!$may_cache) and hook_init() with the 5.x version of my FeedBurner module, so I'm pretty sure I had a good understanding of the problem. I have committed the patch from #25 with a few small modifications. This should now be fixed. Thanks!

#31

DamienMcKenna - January 27, 2009 - 21:11

Thanks Dave!

#32

System Message - February 10, 2009 - 21:20
Status:fixed» closed

Automatically closed -- issue fixed for 2 weeks with no activity.

 
 

Drupal is a registered trademark of Dries Buytaert.