Example #1
0
 public static function write($file, $data)
 {
     if (self::is_enabled()) {
         $file = self::get_root() . preg_replace('{[^' . self::$whitelist . ']}i', '-', $file);
         $lock = new \phpbb\lock\flock($file);
         $lock->acquire();
         if ($handle = @fopen($file, 'wb')) {
             fwrite($handle, $data);
             fclose($handle);
             phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE);
             $return_value = true;
         } else {
             $return_value = false;
         }
         $lock->release();
         return $return_value;
     }
     return false;
 }
 /**
  * Save queue
  */
 function save()
 {
     if (!sizeof($this->data)) {
         return;
     }
     $lock = new \phpbb\lock\flock($this->cache_file);
     $lock->acquire();
     if (file_exists($this->cache_file)) {
         include $this->cache_file;
         foreach ($this->queue_data as $object => $data_ary) {
             if (isset($this->data[$object]) && sizeof($this->data[$object])) {
                 $this->data[$object]['data'] = array_merge($data_ary['data'], $this->data[$object]['data']);
             } else {
                 $this->data[$object]['data'] = $data_ary['data'];
             }
         }
     }
     if ($fp = @fopen($this->cache_file, 'w')) {
         fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$this->queue_data = unserialize(" . var_export(serialize($this->data), true) . ");\n\n?>");
         fclose($fp);
         phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE);
         $this->data = array();
     }
     $lock->release();
 }
Example #3
0
 /**
  * Write cache data to a specified file
  *
  * 'data_global' is a special case and the generated format is different for this file:
  * <code>
  * <?php exit; ?>
  * (expiration)
  * (length of var and serialised data)
  * (var)
  * (serialised data)
  * ... (repeat)
  * </code>
  *
  * The other files have a similar format:
  * <code>
  * <?php exit; ?>
  * (expiration)
  * (query) [SQL files only]
  * (length of serialised data)
  * (serialised data)
  * </code>
  *
  * @access private
  * @param string $filename Filename to write
  * @param mixed $data Data to store
  * @param int $expires Timestamp when the data expires
  * @param string $query Query when caching SQL queries
  * @return bool True if the file was successfully created, otherwise false
  */
 function _write($filename, $data = null, $expires = 0, $query = '')
 {
     global $phpEx;
     $filename = $this->clean_varname($filename);
     $file = "{$this->cache_dir}{$filename}.{$phpEx}";
     $lock = new \phpbb\lock\flock($file);
     $lock->acquire();
     if ($handle = @fopen($file, 'wb')) {
         // File header
         fwrite($handle, '<' . '?php exit; ?' . '>');
         if ($filename == 'data_global') {
             // Global data is a different format
             foreach ($this->vars as $var => $data) {
                 if (strpos($var, "\r") !== false || strpos($var, "\n") !== false) {
                     // CR/LF would cause fgets() to read the cache file incorrectly
                     // do not cache test entries, they probably won't be read back
                     // the cache keys should really be alphanumeric with a few symbols.
                     continue;
                 }
                 $data = serialize($data);
                 // Write out the expiration time
                 fwrite($handle, "\n" . $this->var_expires[$var] . "\n");
                 // Length of the remaining data for this var (ignoring two LF's)
                 fwrite($handle, strlen($data . $var) . "\n");
                 fwrite($handle, $var . "\n");
                 fwrite($handle, $data);
             }
         } else {
             fwrite($handle, "\n" . $expires . "\n");
             if (strpos($filename, 'sql_') === 0) {
                 fwrite($handle, $query . "\n");
             }
             $data = serialize($data);
             fwrite($handle, strlen($data) . "\n");
             fwrite($handle, $data);
         }
         fclose($handle);
         if (function_exists('opcache_invalidate')) {
             @opcache_invalidate($this->cache_file);
         }
         try {
             $this->filesystem->phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE);
         } catch (\phpbb\filesystem\exception\filesystem_exception $e) {
             // Do nothing
         }
         $return_value = true;
     } else {
         $return_value = false;
     }
     $lock->release();
     return $return_value;
 }
Example #4
0
 public function test_concurrent_locking()
 {
     if (!function_exists('pcntl_fork')) {
         $this->markTestSkipped('pcntl extension and pcntl_fork are required for this test');
     }
     $path = __DIR__ . '/../tmp/precious';
     $pid = pcntl_fork();
     if ($pid) {
         // parent
         // wait 0.5 s, acquire the lock, note how long it took
         sleep(1);
         $lock = new \phpbb\lock\flock($path);
         $start = microtime(true);
         $ok = $lock->acquire();
         $delta = microtime(true) - $start;
         $this->assertTrue($ok);
         $this->assertTrue($lock->owns_lock());
         $this->assertGreaterThan(0.5, $delta, 'First lock acquired too soon');
         $lock->release();
         $this->assertFalse($lock->owns_lock());
         // acquire again, this should be instantaneous
         $start = microtime(true);
         $ok = $lock->acquire();
         $delta = microtime(true) - $start;
         $this->assertTrue($ok);
         $this->assertTrue($lock->owns_lock());
         $this->assertLessThan(0.1, $delta, 'Second lock not acquired instantaneously');
         // reap the child
         $status = null;
         pcntl_waitpid($pid, $status);
     } else {
         // child
         // immediately acquire the lock and sleep for 2 s
         $lock = new \phpbb\lock\flock($path);
         $ok = $lock->acquire();
         $this->assertTrue($ok);
         $this->assertTrue($lock->owns_lock());
         sleep(2);
         $lock->release();
         $this->assertFalse($lock->owns_lock());
         // and go away silently
         pcntl_exec('/usr/bin/env', array('true'));
     }
 }