Any AJAX requests that go on during the 'configure site' install task (timezone, clean URL test) trigger drupal_page_footer() -> system_run_automated_cron(), running cron on a partially installed site (and before cron is run explicitly by the installer). This causes weird and unpredictable issues, so system_run_automated_cron() should be disabled until the 'finished' step is reached. For that matter, most of the cache-related stuff in drupal_page_footer() shouldn't run during the installer.

This is marked critical because it blocks the best solution to #831080: Dashboard is completely empty after installation, which is also critical.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

carlos8f’s picture

Status: Active » Needs review
FileSize
2.93 KB

This patch takes the approach that MAINTENANCE_MODE should be defined consistently during those AJAX requests to index.php, just as it is during requests to install.php. Then drupal_page_footer() uses MAINTENANCE_MODE to determine if it should run cron and end-of-request caching.

catch’s picture

If the only issue here is the auto cron, then I don't see why we couldn't disable it (either off by default or via $conf) right up until it's run by the installer, then we wouldn't need any additional runtime code to handle that case. The cache stuff shouldn't be run, but all the drupal fake cache exists to prevent that and other cache_set() which could be called from somewhere other than drupal_page_footer()).

carlos8f’s picture

OK, here we're skipping the MAINTENANCE_MODE stuff and just focusing on suppressing auto cron.

catch’s picture

Seems better to me, but I think we should put the variable check inside system_run_automated_cron() itself. Otherwise looks RTBC.

moshe weitzman’s picture

I'll just add that we need a non hackish way to disable the auto cron during install. There is no way to do that now that I can see. Many installs will be performed by drush site-install and those scripts are quite capable of calling drush cron after installation if they choose.

I was thinking that we should call system_run_automated_cron() from the installer instead of directly calling drupal_cron_run() so that a profile could set cron_safe_threshold=0 and skip cron during install.

carlos8f’s picture

Rolled with @catch and @moshe suggestions. Using system_run_automated_cron() instead of drupal_cron_run() is minor enough to include here (I think). Easy to add while we are patching this part of the installer.

David_Rothstein’s picture

Instead of a new variable, isn't it possible to just use the existing 'install_task' variable here (check if it's equal to 'done' or not)?

Otherwise, I guess this patch makes sense since running cron more than once during the installer is pretty wasteful anyway, but geez, the fact that this is currently the only way to solve #831080: Dashboard is completely empty after installation is pretty scary. There is something going on in Drupal that none of us understand yet :)

carlos8f’s picture

What's not to understand? :) I noted that this is the *best* (not only) way to solve the dashboard issue, and it's not that mysterious: _block_rehash() permanently resets regions that it can't find in a theme, and when run on a partially installed
site (and no MAINTENANCE_MODE defined) no wonder it can't find the dashboard regions.

I'll look into using the 'install_task' variable, although I kind of like the specialness of 'installing'. A special temporary variable can't hurt right?

catch’s picture

The installer making ajax requests, which then cause caches (and etc.) to be populated which otherwise shouldn't has been known for a while now, this is why DrupalFakeCache actually tries to delete from cache tables despite never putting anything in them allegedly. Problem is that all the bugs that arise from it are very strange and hard to track down, last one I remember was the site name being wrong after install but fixing itself as soon as you refreshed the page.

David_Rothstein’s picture

I remember it well - I wrote that part of the DrupalFakeCache code :) The reason I think this is surprising is that the Dashboard module is already fully installed well before _block_rehash() gets called (I think several page requests before), and all those cache clearings in between still don't manage to fix whatever out-of-date data is causing this bug and allow its regions to be recognized...

carlos8f’s picture

The problem is that we are assuming the dashboard is 'fully installed', and yet {system} is not rebuilt yet. See my post at the dashboard issue: http://drupal.org/node/831080#comment-3119622

DrupalFakeCache doesn't help us here, unfortunately. The stale caches involved are not related to cache_set/get(), they are the list_themes() static cache and {system}, which is a type of cache too. Further, DrupalFakeCache isn't running on these ajax requests, as far as I can tell (we're on index.php). We could add by doing:


if (variable_get('installing', FALSE)) {
  $conf['cache_default_class'] = 'DrupalFakeCache';
}

but it would be more of a preventative measure and wouldn't help us with static or {system} caches.

Maybe we need to look at rebuilding the {system} table in module_enable(), since that would make it more self-contained and not have to depend on system_module_submit()/drupal_flush_all_caches()/system_rebuild_*_data() or what have you.

Time to look at #651086: Cache clearing is an ineffective mess in module_enable() and system_modules_submit() again?

carlos8f’s picture

Here's a reroll using 'install_task' instead of 'installing'.

I think it would be ideal to also put in $conf['cache_default_class'] = 'DrupalFakeCache'; and define('MAINTENANCE_MODE', 'install') also, so we are mirroring the environment of install.php for those ajax requests. If that seems non-trivial, it might be a candidate for a non-critical followup patch or issue.

catch’s picture

This version looks fine to me.

David_Rothstein’s picture

Status: Needs review » Needs work

I think with this patch, the install_task variable won't necessarily wind up 'done' at the end of the installation, because there is no actual guarantee that install_finished() is the last task that will run in all installation profiles...

Also, it seems that complication is only necessary to support this part of the patch:

-  drupal_cron_run();
+  // Profiles may choose to opt out of auto cron by calling
+  // variable_set('cron_safe_threshold', 0).
+  system_run_automated_cron();

But looking at that, I am thinking it's not actually a good idea anyway? If a profile just wants to set the 'cron_safe_threshold' variable to 0 for use in the site itself, it shouldn't be forced to get this change in installation behavior as a side effect. If profiles need a way to opt out of this (I'm not sure I understand what the use case is - but maybe a profile that creates so much stuff that the first cron run will take a really long time and it doesn't want the person installing the site to have to sit there waiting for it?) then I think we need another method. How about we leave that for another issue, since it wasn't part of the original issue anyway?

David_Rothstein’s picture

Status: Needs work » Needs review
FileSize
1.28 KB

So if we strip that part out we basically have a one line patch (I added a code comment too, though). Maybe we can go with this, and leave allowing profiles to entirely opt out of cron to another issue?

carlos8f’s picture

Good points. I'll reroll yet again :]

carlos8f’s picture

cross posted. #16 code looks good, comment is a little verbose. I would probably keep it to something like, "If the site is not fully installed, suppress auto cron. Otherwise it could be triggered unnecessarily by ajax requests during installation."

David_Rothstein’s picture

The shortened comment sounds good to me. Here it is with something very similar to that.

catch’s picture

Status: Needs review » Reviewed & tested by the community

Looks great.

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Committed to HEAD, thanks! That one-liner is nice and elegant.

Agreed on pushing the disabling of this behaviour to a separate issue. Since D6 didn't have this capability, this smells like a D8 feature, for possible backport to D7 and D6 once it's in.

Status: Fixed » Closed (fixed)

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