Want to get Lullabot article, videocast, and podcast announcements delivered right to your in-box? Let us know your email address (we won't share it) and we'll let you know when anything exciting happens.

How I Crashed Lullabot.com

The other day I (this is ted, by the way, I'll take blame for this one ;-)) was working on the new TWiT site when I accidentally crashed all of Lullabot.com, oops.

How did I do it? Well quite subtly. Take a look at this code, can you figure it out?

  $query = db_query('SELECT tid FROM {term_data} WHERE vid = %d', $vid);
 
  while ($result = db_result($query)) {
    $tids[] = $result;
  }

See it? Well the obvious answer can easily be figured out. Based on this code, obviously that loop must be infinite and that array grows so large that eats up all the memory. But why does it?

Well it turns out that db_result($query) is a wrapper for mysql_result() which returns either a result set or FALSE if none can be found.

But, unlike mysql_fetch_array() or mysql_fetch_object() (corresponding Drupal wrappers are db_fetch_array() and db_fetch_object()), this function does not increase the result pointer to the next one. Hence, when you put this in a loop, it'll be infinite because $result is always true (e.g., returning that first row and never getting to a pointer that is FALSE), and you'll end up creating a giganitic array that eats up your memory.

So why post about this seemingly mundane problem? Well to illustrate a point--despite all of Drupal's wonderful APIs and wrapper functions, you can still do really stupid things, that well, bring down entire servers quite easily :-)

And yes, this problem is a bit specific to our case, since we control our whole server and have setup PHP to handle large file uploads for our videocasts.

But nonetheless, lesson learned.

Comments on this post will automatically be closed three months from the original post date.

Comments

Oh Man! I did the exact same

Oh Man! I did the exact same thing! My chat module was causing my system uptime to jump and I couldn't figure out why. Sure enough it was good old db_result in while-loop.

I blame perl :-)