We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 36885
    • 15 Posts
    This has now happened again and I cannot reproduce it.
    I can upload files through MODx and it seems that MODx creates the files correctly in the cache folder.

    I have narrowed it down to 'modcachemanager.class' and the following rows (example for system_settings, applies to the all same error messages in the file):
    if (!$this->set('config', $config, $lifetime, $options)) {
    $this->modx->log(modX::LOG_LEVEL_ERROR, 'Could not cache system settings.');
    }

    As the files gets created but contains no content, can it be a bug in MODx cache manager?
    How can I check when '$this->set('config', $config, $lifetime, $options)' fails and why?

    Example:
    core/cache/action_map/mgr/actions.cache.php is created but no content
    core/cache/logs/error.log is created and contains the error log information (as provided above).
      • 36885
      • 15 Posts
      Now I had the time to dig into this in detail.

      modxcachemanager.class.php extends xpdocachemanager.
      The set function in xpdo calls tje writeFile function, and here it is where it fails.

      Added some log-code to xpdocachemanager.class.php:
          public function writeFile($filename, $content, $mode= 'wb', $options= array()) {
      $fh = fopen('/www/webvol17/40/9cn1xungy6qci7w/test.boxma.se/public_html/debug_log.txt', 'a');
      fwrite($fh, 'xpdocachemanager.class.php: Inside writeFile-function.'. ".\n");
              $written= false;
              if (!is_array($options)) {
                  $options = is_scalar($options) && !is_bool($options) ? array('new_folder_permissions' => $options) : array();
              }
              $dirname= dirname($filename);
              if (!file_exists($dirname)) {
                  $this->writeTree($dirname, $options);
              }
              $mode = str_replace('+', '', $mode);
              switch ($mode[0]) {
                  case 'a':
                      $append = true;
                      break;
                  default:
                      $append = false;
                      break;
              }
              $fmode = (strlen($mode) > 1 && in_array($mode[1], array('b', 't'))) ? "a{$mode[1]}" : 'a';
              $file= @fopen($filename, $fmode);
              if ($file) {
                  if ($append === true) {
      fwrite($fh, 'xpdocachemanager.class.php: $append = true. $filename:' . $filename . ".\n");
                      $written= fwrite($file, $content);
                  } else {
      fwrite($fh, 'xpdocachemanager.class.php: $append = false. $filename:' . $filename . ".\n");
                      $locked = false;
                      $attempt = 1;
                      $attempts = (integer) $this->getOption(xPDO::OPT_CACHE_ATTEMPTS, $options, 1);
      fwrite($fh, 'xpdocachemanager.class.php: $attempts:' . $attempts . ". $filename: " . $filename . ".\n");
                      $attemptDelay = (integer) $this->getOption(xPDO::OPT_CACHE_ATTEMPT_DELAY, $options, 1000);
      fwrite($fh, 'xpdocachemanager.class.php: $attemptDelay:' . $attemptDelay . ". $filename: " . $filename . ".\n");
                      while (!$locked && ($attempts === 0 || $attempt <= $attempts)) {
                          $locked = flock($file, LOCK_EX | LOCK_NB);
      if ($locked == true) fwrite($fh, 'xpdocachemanager.class.php: Inside while loop. $locked = true. $filename:' . $filename . ".\n");
      if ($locked == false) fwrite($fh, 'xpdocachemanager.class.php: Inside while loop. $locked = false. $filename:' . $filename . ".\n");
                          if (!$locked && $attemptDelay > 0 && ($attempts === 0 || $attempt < $attempts)) {
      if ($locked == false) fwrite($fh, 'xpdocachemanager.class.php: usleep. $filename:' . $filename . ".\n");
                              usleep($attemptDelay);
                          }
                          $attempt++;
                      }
                      if ($locked) {
      fwrite($fh, 'xpdocachemanager.class.php: $locked = true. $filename:' . $filename . ".\n");
                          fseek($file, 0);
                          ftruncate($file, 0);
                          $written= fwrite($file, $content);
      if ($written == false) fwrite($fh, 'xpdocachemanager.class.php: $locked = true. $written = false. $filename:' . $filename . ".\n");
      if ($written == true) fwrite($fh, 'xpdocachemanager.class.php: $locked = true. $written = true. $filename:' . $filename . ".\n");
                          flock($file, LOCK_UN);
                      }
                  }
                  @fclose($file);
              }
      if ($written == false) fwrite($fh, 'xpdocachemanager.class.php: $written = false. $filename:' . $filename . ".\n");
      if ($written == true) fwrite($fh, 'xpdocachemanager.class.php: $written = true. $filename:' . $filename . ".\n");
      fclose($fh);
              return ($written !== false);
          }


      Example of output:
      xpdocachemanager.class.php: Inside set-function..
      xpdocachemanager.class.php: $fileName:./www/webvol17/40/9cn1xungy6qci7w/test.boxma.se/public_html/core/cache/system_settings/config.cache.php.
      xpdocachemanager.class.php: Before writeFile-function..
      xpdocachemanager.class.php: Inside writeFile-function..
      xpdocachemanager.class.php: $append = false. $filename:/www/webvol17/40/9cn1xungy6qci7w/test.boxma.se/public_html/core/cache/system_settings/config.cache.php.
      xpdocachemanager.class.php: $attempts:1. /www/webvol17/40/9cn1xungy6qci7w/test.boxma.se/public_html/core/cache/system_settings/config.cache.php: /www/webvol17/40/9cn1xungy6qci7w/test.boxma.se/public_html/core/cache/system_settings/config.cache.php.
      xpdocachemanager.class.php: $attemptDelay:1000. /www/webvol17/40/9cn1xungy6qci7w/test.boxma.se/public_html/core/cache/system_settings/config.cache.php: /www/webvol17/40/9cn1xungy6qci7w/test.boxma.se/public_html/core/cache/system_settings/config.cache.php.
      xpdocachemanager.class.php: Inside while loop. $locked = false. $filename:/www/webvol17/40/9cn1xungy6qci7w/test.boxma.se/public_html/core/cache/system_settings/config.cache.php.
      xpdocachemanager.class.php: $locked = false. $filename:/www/webvol17/40/9cn1xungy6qci7w/test.boxma.se/public_html/core/cache/system_settings/config.cache.php.
      xpdocachemanager.class.php: $written = false. $filename:/www/webvol17/40/9cn1xungy6qci7w/test.boxma.se/public_html/core/cache/system_settings/config.cache.php.
      


      Analyzing the output, it seems that MODx sets $append to false and goes into the while loop as it shold.
      Here $locked should be set to true with '$locked = flock($file, LOCK_EX | LOCK_NB);'
      But $locked is set to false.
      Therefore the 'if ($locked)' clause does not trigger.

      What I did as a work-around, was to add so the fwrite was triggered even at $locked = false:
                      if ($locked) {
                          fseek($file, 0);
                          ftruncate($file, 0);
                          $written= fwrite($file, $content);
                          flock($file, LOCK_UN);
                      } else {
      	$written= fwrite($file, $content);
      }


      Now. The question is if this is a bug in MODx, or a feature/bug in the flock-function as it seems that it returns a false value.
      Or is it so, that flock is intended to return false and that the function needed to catch the false statement as well?

      Shall i trigger this as a bug in MODx?

      Regards
      Sven
        • 36885
        • 15 Posts
        I have confirmed with my current hosting partner, that they have NFS and freeBSD.
        So most likely it is related to PHP <-> FreeBSD <->NFS that gives the error.
        There are notes at php.net with flock() in regards to multithreaded environments and NFS.
        And my hosting partner fits both.

        So therefore the recommendation is to check that your hosting partner does not run at least NFS that can cause problems with flock() and subsequently problems with cache and xpdocachemanager.
          • 7667
          • 13 Posts
          Hi there.

          I am having very similar issues and have tried this work around with no success. Would you or anyone else happen to have any insight on this matter?

          I have talked to my hosting provider and they do use NFS.

          I am not that knowledgeable in regards to php and server environments. What I do know is that my sites were working, I cleared the cache and now it's not. Same issue, every thing in the cache folder is 0 bytes.

          Hopefully someone has some insight. Thanks.

          Derrick
            • 36885
            • 15 Posts
            Hi Derrick
            I moved to another hosting partner that did not use NFS. Both quicker and without the bug.

            It might have been solved in 2.2.5 through http://tracker.modx.com/issues/8420
            Have you tried testing with 2.2.5?

            Regards
            Sven
              • 7667
              • 13 Posts
              Quote from: slittorin1 at Dec 07, 2012, 12:47 PM
              Hi Derrick
              I moved to another hosting partner that did not use NFS. Both quicker and without the bug.

              It might have been solved in 2.2.5 through http://tracker.modx.com/issues/8420
              Have you tried testing with 2.2.5?

              Regards
              Sven

              Thanks slittorin1,
              I did try 2.2.5 and it did not work, so I did what you did and switch hosting providers smiley

              Derrick