When I clear the cache my cache, I recv the following error (several instances of it):

Invalid argument supplied for foreach() in /var/www/drupal-6/sites/all/modules/cacherouter/engines/apc.php on line 121

That line resides in the delete() function (which makes sense).

  function delete($key) {
    // Remove from static array cache.
    parent::delete($key);
    
    if (substr($key, -1, 1) == '*') {
      $key = substr($key, 0, strlen($key) - 1);
      $lookup = apc_fetch($this->lookup);
      foreach ($lookup as $k => $v) {  <--- line 121
        if (substr($k, 0, strlen($key) - 1)) {
          apc_delete($k);
          unset($lookup[$k]);  
        }
      }

(IIRC)I also had this problem with xcache installed (obviously it would say xcache.php, but I removed xcache for other reasons so I cannot say for sure).

I haven't done any real debugging, but with some print_r()'s to syslog it looks like apc_fetch is sometimes returning an empty array ('Array()'). In my case, the original $key/s passed to that function that caused apc_fetch to return an empty array were 'links:devel:*', 'links:navigation:*', and '*'.
I do not know how to go any further w/o a debugger (like, who is the caller, did those $keys ever get apc_store'd, etc..).

I am using Drupal 6.6/debian lenny kernel 2.6.24-19-xen x86_64/apache2/php5+suhoisin patch/APC-3.0.19 on a VPS, and am using the latest cacherouter files from CVS.

Thanks,
Mike Waters

Comments

Mike_Waters’s picture

SOLUTION: (?)
The code doesn't check for a FALSE return value of apc_fetch(), so $lookup is sometimes FALSE/0. When php tries to parse 0 into an associative array, the error handler is invoked.
I don't know how to create a patch, but you want to replace

      $lookup = apc_fetch($this->lookup);

        foreach ($lookup as $k => $v) {
          
          if (substr($k, 0, strlen($key) - 1)) {
            apc_delete($k);
            unset($lookup[$k]);  
          }
        }

with

      $lookup = apc_fetch($this->lookup);
      if ($lookup != FALSE) {

        foreach ($lookup as $k => $v) {
          
          if (substr($k, 0, strlen($key) - 1)) {
            apc_delete($k);
            unset($lookup[$k]);  
          }
        }
      }

at line 120 of engines/apc.php.

I don't know much about the apc engine, so I can't say whether or not it is correct for apc_fetch() to ever return FALSE, and so can't say that this is a valid solution.
Wish I could help more, but I am debugging a remote server (across the country) so I only have what source code xdebug sends to my IDE over the wire (there's no 'step backward', and if I 'step into'd through the entire drupal bootstrap my F11 key would have blood on it ;).

Thanks for the great module.
-Mike Waters

slantview’s picture

Status: Active » Postponed (maintainer needs more info)

Can you tell me what version you are using? In the latest version, before I run over the lookup table, I check if it is "empty" with the php empty() function. Per the documentation on php.net:


Return Values

Returns FALSE if var has a non-empty and non-zero value.

The following things are considered to be empty:

    * "" (an empty string)
    * 0 (0 as an integer)
    * "0" (0 as a string)
    * NULL
    * FALSE
    * array() (an empty array)
    * var $var; (a variable declared, but without a value in a class)

You can see that in apc.php on line 158.

<?php
  function flush() {
    $this->lock();

    // Get lookup table to be able to keep track of bins
    $lookup = apc_fetch('lookup_' . $this->name);

    // If the lookup table is empty, remove lock and return
    if (empty($lookup)) {
      $this->unlock();
      return TRUE;
    }

    // Cycle through keys and remove each entry from the cache
    foreach ($lookup as $k => $v) {
      if (apc_delete($k)) {
        unset($lookup[$k]);
      }
    }

    // Resave the lookup table (even on failure)
    apc_store('lookup_' . $this->name, $lookup);

    // Remove lock
    $this->unlock();

    return TRUE;
  }
?>
Mike_Waters’s picture

I am using the version from CVS as of 10/25/08. My copy of apc.php is identical to what you've posted.

Why would cache clearing even hit the delete() function? It looks like flush() calls apc_delete() directly.
Something I probably should have noted is that this error was the result of using the Devel modules 'Clear cache' function. It did not occur to me that Devel might use a separate cache clearing implementation; does it?.
(Note that I am not saying that Site Configuration->Performance->Clear Cache *didn't* cause the error, because I don't use it and so don't know.)

EDIT: migrating to the cvs version caused the apc_fix_lock patch to revert. Could this have anything to do with it?

Thanks,
Mike Waters

michtoen’s picture

i got the same error using apc with current release version and d6.10

i had cache browser and cache_path installed too

aaronshaf’s picture

Same problem here

kenorb’s picture

same problem

Flying Drupalist’s picture

And here too!

Edit: Not getting this anymore when updated to latest dev.

michtoen’s picture

It seems to me it happens when the cache table is clear or fresh.

I don't get that when i clear the cache here and there but when i install modules or remove and
then i clear the cache by hand 1 or 2 times, then it happens.

Because the error msg is in a forearch() it smells a bit like an empty var run.

sidharth_k’s picture

subscribing

a_c_m’s picture

same problem

kenorb’s picture

Status: Postponed (maintainer needs more info) » Active
kenorb’s picture

Title: Error when clearing cache » Error when clearing cache and on update.php

The same error on update.php
Is this module is abandoned?

slantview’s picture

Status: Active » Fixed

This is fixed now.

Status: Fixed » Closed (fixed)

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