I prepare to stand corrected on this, but take a look at lines 589 to 603 of includes/theme.inc in Drupal 7:

    // Extract from the database only when it is available.
    // Also check that the site is not in the middle of an install or update.
    if (!defined('MAINTENANCE_MODE')) {
      try {
        $themes = system_list('theme');
      }
      catch (Exception $e) {
        // If the database is not available, rebuild the theme data.
        $themes = _system_rebuild_theme_data();
      }
    }
    else {
      // Scan the installation when the database should not be read.
      $themes = _system_rebuild_theme_data();
    }

This behaviour is the same as it is in Drupal 6, and I strongly suspect it is causing issues there. Firstly, there is a phantom ctools bug on high-traffic sites: #979912: Panels cache getting stuck, getting white screen on my homepage panel.

Secondly, I have observed throughout the life of Drupal 6 that at times when the database is very sluggish there is an intermittent bug that disables all themes. (I have observed this behaviour on several sites, I still get it, and I have never seen a fix.)

My theory (and it is only a theory) is this. If there is a problem and the database goes away, even temporarily (which tends to manifest mainly only on very busy sites) at the moment when list_themes() is called, because of the lines that revert to reading the .info files when the database goes away, it's possible both contrib modules, and occasionally even core, read themes as disabled (because the info files contain no status information required to determine if the theme is enabled or not) and this leads to knock-on effects.

In the case of ctools, perhaps the failure to acknowledge plugins. With core, perhaps this is the cause of the phantom theme disabling on busy sites I've observed in Drupal 6.

Regardless, question is this: do we actually need this code at all?

      catch (Exception $e) {
        // If the database is not available, rebuild the theme data.
        $themes = _system_rebuild_theme_data();
      }

What are the consequences of removing it? Is anything else relying on this behaviour? If not, perhaps it should go?

I must stress, this is intelligent guess-work for now, as this bug is very difficult to track down being as it only seems to show itself intermittently on very busy production Drupal sites, but I'd like someone to consider it at least and tell me if I'm going crazy... ;-)

Comments

greg.harvey’s picture

Further thinking on this... it occurs to me list_themes() tries to do too much. Detecting the database during the call to this function is fraught with dangers. It might be temporarily unavailable, in which case the returned $theme objects will not take the expected form.

I would suggest list_themes() should be split in to two separate functions - one for when the database is *not* expected to be available and one for when the database should be normally available. That way the latter can behave consistently and other parts of Drupal relying on the former have their own function to call.