Home > Development, Drupal, English, php, Techie > The Drupal 6 bootstrap easy debug

The Drupal 6 bootstrap easy debug

Just as a self reminder, and because I don’t fancy too much looking into the Drupal core for debugging, here is a short explanation of how the Drupal 7 bootstrap mechanism works.

First of all, a bootstrap mechanism is a mechanism by which you work progressively your way through the full loading of a system, step by step, starting with the loading of simple elements that will allow you to load more complex elements. The Linux system also has a bootstrap mechanism (as do most OSes). For operating systems, bootstrapping means you first load a little bit of code which will enable the computer to know how to deal with memory and compiled code, which then allows you to load the Linux kernel, which then allows you to load (and executre) much more stuff, like your desktop interface, etc.

So in Drupal, as you might have realized, everything goes through the /index.php file, which looks like this:

require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

$return = menu_execute_active_handler();

// Menu status constants are integers; page content is a string.
if (is_int($return)) {
  switch ($return) {
    case MENU_NOT_FOUND:
      drupal_not_found();
      break;
    case MENU_ACCESS_DENIED:
      drupal_access_denied();
      break;
    case MENU_SITE_OFFLINE:
      drupal_site_offline();
      break;
  }
}
elseif (isset($return)) {
  // Print any value (including an empty string) except NULL or undefined:
  print theme('page', $return);
}

drupal_page_footer();

We are only interested in the first bit here (the bootstrap):

require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

This bit literally tells us “load the bootstrap library” then “call the bootstrap mechanism with the level of bootstrap DRUPAL_BOOTSTRAP_FULL”.

For practical reasons, the DRUPAL_BOOTSTRAP_FULL constant’s value is actually 8, but it is called DRUPAL_BOOTSTRAP_FULL to make it more human. Incidentally, this constant is defined at the beginning of the included file “bootstrap.inc”.

Now as you see we wall the drupal_bootstrap() function, also located in bootstrap.inc (quite down the file, at line 1305). Let’s see what it does.

function drupal_bootstrap($phase) {
  static $phases = array(DRUPAL_BOOTSTRAP_CONFIGURATION, DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE, DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), 
    $phase_index = 0;

  while ($phase >= $phase_index && isset($phases[$phase_index])) {
    $current_phase = $phases[$phase_index];
    unset($phases[$phase_index++]);
    _drupal_bootstrap($current_phase);
  }
}

As we can see here, we prepare an array of “steps”. Because of the definition of each of the constants used here, this array is actually: $phases[0=>0,1=>1,2=>2,3=>3,4=>4,5=>5,6=>6,7=>7,8=>8], 8 being DRUPAL_BOOTSTRAP_FULL as we have seen previously.

So when calling this function, the index.php calls it with the value 8. The while condition that follows says this:

While 8 is greater than the $phase_index (initially 0) and while there is a value for the $phases array element with index of $phase_index set $current_phase to the current $phase_index unset the element of the $phases array that has the index of $phase_index AND increase $phase_index (so the next iteration executes the next $phases array element) call the _drupal_bootstrap() function with the $current_phase (0 in the first case, then 1, then 2, etc up to 8) 

So the idea is that drupal_bootstrap() is the progressive mechanism that makes several levels of bootstrap execute.

If we move to the next step (the _drupal_bootstrap() function), we see the following structure:

  switch ($phase) {

    case DRUPAL_BOOTSTRAP_CONFIGURATION:
      drupal_unset_globals();
      timer_start('page');
      conf_init();
      break;

    case DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE:
      require_once variable_get('cache_inc', './includes/cache.inc');
      if (variable_get('page_cache_fastpath', FALSE) && page_cache_fastpath()) {
        exit;
      }
      break;

    case DRUPAL_BOOTSTRAP_DATABASE:
      ...

So we are indeed simply executing a separate bit of code for each level of the bootstrap of Drupal.

Sometimes you might have problems ocurring during any phase of the bootstrap. To help you identify which step is broken, one (quite extreme – don’t use in production) method is to add calls to the die() function in any of these steps, and see if your drupal page prints the message you give into the die() call.

For example, to hack the first level:

    case DRUPAL_BOOTSTRAP_CONFIGURATION:
      drupal_unset_globals();
      die('called drupal_unset_globals() successfully');
      timer_start('page');
      conf_init();
      break;

This type of construction will fail after calling drupal_unset_globals(), but if you used to have a blank screen, you will now get an error message that tells you that the previous step worked. And you can thus work your way down the bootstrap in much the same way:

    case DRUPAL_BOOTSTRAP_CONFIGURATION:
      drupal_unset_globals();
      timer_start('page');
      conf_init();
      die('called conf_init() successfully');
      break;

Once you really get a blank screen again, you know that the previous step failed. You have thus got much closer from the real problem. The next step would then be to get into the last function called and use the die() technique again.

If you want to do that on a production server, use error_log() instead of die(). This will not show anything on your web page but it will register it in your Apache (or other web server) error log (generally something like /var/log/apache2|httpd/error_log), which will let your normal users use other parts of the website without realizing you are debugging, but still let you debug.

I hope this might have helped some of you starting with Drupal development/debugging. Don’t hesitate to leave me a message if it did, I appreciate it.

      die('called drupal_unset_globals() successfully');
Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: