PHP4.3.3でcakePHPのキャッシュ機能が使えない

May 10, 2010,
tags: cakephp php php4.3.3 エラー キャッシュ


このエントリーをはてなブックマークに追加

PHP4.3.3(CGI版)でcakePHP1.2.7を動かしてみたところ、以下のようなエラーがでました。

Warning: fread(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 172

Warning: fclose(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 270

Warning: fwrite(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 240

Warning: fclose(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 270

Warning: fread(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 172

Warning: fclose(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 270

Warning: fwrite(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 240

Warning: fclose(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 270

しかもこんな感じのメッセージが大量に・・・。

どうやらキャッシュ機能がうまく動作していないようで、とりあえずキャッシュを使わないように設定してみた。
app/config/core.php

Configure::write('Cache.disable', true);

一応エラーメッセージはでなくなったけど、キャッシュ使えないのは致命的だということえ、とりあえずどういう状況下調べてみました。
とりあえず、原因としてどうやらキャッシュを読み書きする際にfopenがおわってfcloseするときに問題が起こっているようです・・・。
だから、cakeのキャッシュをfileで行っているからぽい。。
もしかしたら、MemcacheとかXcacheとかAPCとかでキャッシュすればエラーにはならないのかなーと思います。

しかし、どうしてもキャッシュ機能をfileでやりたいので、もうすこし調べることに。
fcloseするときにおかしいので、とりあえず、「cake/libs/file.php」のcloseメソッドをいじって実験してみる。

function close() {
		echo &quot;close in 01<br>&quot;;
		if (!is_resource($this->handle)) {
			return true;
		}
			echo &quot;close in 02 <br>&quot;;
		//return fclose($this->handle);

		$flag = fclose($this->handle);
		//var_dump($this->handle);
		//echo &quot;<br>&quot;;
		exit();
	}

これでブラウザからindex.phpにアクセスすると・・・以下のような結果になる。

close in 01
close in 02
close in 01
close in 02

Warning: fread(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 176
close in 01
close in 02

Warning: fclose(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 278

これはどういうことだ・・・。
たぶん、close in 01 と02が2回ずつでてくるのはデストラクタで呼ばれているから2回でてくるのはわかるんですが、そのあとにfreadが呼ばれている理由がわからない・・・。
とりあえず、readに適当にechoを入れてみる。

function read($bytes = false, $mode = 'rb', $force = false) {
		echo &quot;file read 01<br>&quot;;
		if ($bytes === false &amp;&amp; $this->lock === null) {
			return file_get_contents($this->path);
		}
		echo &quot;file read 02<br>&quot;;
		if ($this->open($mode, $force) === false) {
			return false;
		}
		echo &quot;file read 03<br>&quot;;
		if ($this->lock !== null &amp;&amp; flock($this->handle, LOCK_SH) === false) {
			return false;
		}
		if (is_int($bytes)) {
			echo &quot;file read 04<br>&quot;;
			return fread($this->handle, $bytes);
		}

		$data = '';
		while (!feof($this->handle)) {
			$data .= fgets($this->handle, 4096);
		}
		$data = trim($data);

		if ($this->lock !== null) {
			flock($this->handle, LOCK_UN);
		}
		if ($bytes === false) {
			$this->close();
		}
		return $data;
	}

実行した結果は以下のとおり。

file read 01
file read 02
file read 03
file read 04
close in 01
close in 02
close in 01
close in 02
file read 01
file read 02
file read 03
file read 04

Warning: fread(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 176
close in 01
close in 02

Warning: fclose(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 278

close in 01と02が2回実行されるところはデストラクタがきいているからなんだろうけど、
そのあとにfreadされてしまっているのはなぜだ?

とりあえずデストラクタをコメントアウトしてみる。

function __destruct() {
	//	$this->close();
	}

おおーエラーが消えた!!
ということで、closeのexitを消してみよう。

あれ、やはりエラーがたくさんでている。。
たぶん、問題としては、closeメソッドでfclose実行された後にfreadが実行されていることなんだとおもう。
で、でもうresourceがcloseした状態なのにfreadをしているからエラーになるんじゃないかな?
てかPHP4だと、デストラクタ自体は存在してなくて、「register_shutdown_function」をつかって実装していくので、その辺で実はfileクラスを呼び出しているデストラクタの問題で、エラーが起きているのかもしれない。
わからないけど・・・。

でcloseメソッドで$this->handleをdumpしてみる。今までいじったコードはすべて元にもどして、closeメソッドだけいじる。

function close() {
		//echo &quot;close in 01<br>&quot;;
		if (!is_resource($this->handle)) {
			return true;
		}
		//echo &quot;close in 02 <br>&quot;;
		//return fclose($this->handle);
		var_dump($this->handle);
		$flag = fclose($this->handle);
		var_dump($this->handle);
		echo &quot;method end<br>&quot;;
		return $flag;
		//echo &quot;<br>&quot;;
		//exit();

	}

結局エラーがでているってことで、もう少し呼び出している上のクラスでexitさせてみよう。
ということで、「cale/libs/configure」クラスのcorePathsメソッドを変更してみる。

function corePaths($type = null) {
		$paths = Cache::read('core_paths', '_cake_core_');
		exit(); //変更箇所
		if (!$paths) {
			$paths = array();
			$openBasedir = ini_get('open_basedir');
			if ($openBasedir) {
				$all = explode(PATH_SEPARATOR, $openBasedir);
				$all = array_flip(array_flip((array_merge(array(CAKE_CORE_INCLUDE_PATH), $all))));
			} else {
				$all = explode(PATH_SEPARATOR, ini_get('include_path'));
				$all = array_flip(array_flip((array_merge(array(CAKE_CORE_INCLUDE_PATH), $all))));
			}
			foreach ($all as $path) {
				if ($path !== DS) {
					$path = rtrim($path, DS);
				}
				if (empty($path) || $path === '.') {
					continue;
				}
				$cake = $path .  DS . 'cake' . DS;
				$libs = $cake . 'libs' . DS;
				if (is_dir($libs)) {
					$paths['libs'][] = $libs;
					$paths['model'][] = $libs . 'model' . DS;
					$paths['behavior'][] = $libs . 'model' . DS . 'behaviors' . DS;
					$paths['controller'][] = $libs . 'controller' . DS;
					$paths['component'][] = $libs . 'controller' . DS . 'components' . DS;
					$paths['view'][] = $libs . 'view' . DS;
					$paths['helper'][] = $libs . 'view' . DS . 'helpers' . DS;
					$paths['cake'][] = $cake;
					$paths['vendor'][] = $path . DS . 'vendors' . DS;
					$paths['shell'][] = $cake . 'console' . DS . 'libs' . DS;
					break;
				}
			}
			Cache::write('core_paths', array_filter($paths), '_cake_core_');
		}
		if ($type &amp;&amp; isset($paths[$type])) {
			return $paths[$type];
		}

		return $paths;
	}

これだと、エラーメッセージはでない。しかし「Cache::write(‘core_paths’, array_filter($paths), ‘_cakecore’);」の下にeixtを書くと以下のようになる。

resource(17) of type (stream) resource(17) of type (Unknown) method end

Warning: fread(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 176
resource(17) of type (Unknown)
Warning: fclose(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 278
resource(17) of type (Unknown) method end

Warning: fwrite(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 244
resource(17) of type (Unknown)
Warning: fclose(): 17 is not a valid stream resource in /var/www/cake/libs/file.php on line 278
resource(17) of type (Unknown) method end

あれ、こんどはreadエラーもでている。。。
うーむわからん。。。

resourceのtypeがUnknownだった場合は、read,write,closeしなければいいんじゃね?とおもったので、「get_resource_type() 」fileクラスを変更してみる。
ということで以下のように変更しました。

最終的な修正
cake/libs/file.php readメソッド

function read($bytes = false, $mode = 'rb', $force = false) {
		if ($bytes === false &amp;&amp; $this->lock === null) {
			return file_get_contents($this->path);
		}
		if ($this->open($mode, $force) === false) {
			return false;
		}
		//追加
		if (get_resource_type($this->handle) == &quot;Unknown&quot; ) {
				return false;
		}
		if ($this->lock !== null &amp;&amp; flock($this->handle, LOCK_SH) === false) {
			return false;
		}
		if (is_int($bytes)) {
			return fread($this->handle, $bytes);
		}

		$data = '';
		while (!feof($this->handle)) {
			$data .= fgets($this->handle, 4096);
		}
		$data = trim($data);

		if ($this->lock !== null) {
			flock($this->handle, LOCK_UN);
		}
		if ($bytes === false) {
			$this->close();
		}
		return $data;
	}

cake/libs/file.php writeメソッド

function write($data, $mode = 'w', $force = false) {
		$success = false;
		if ($this->open($mode, $force) === true) {
			if ($this->lock !== null) {
				if (flock($this->handle, LOCK_EX) === false) {
					return false;
				}
			}
			//追加
			if (get_resource_type($this->handle) == &quot;Unknown&quot; ) {
					return false;
			}
			if (fwrite($this->handle, $data) !== false) {
				$success = true;
			}
			if ($this->lock !== null) {
				flock($this->handle, LOCK_UN);
			}
		}
		return $success;
	}

cake/libs/file.php closeメソッド

function close() {
		if (!is_resource($this->handle)) {
			return true;
		}
		//変更
		if (get_resource_type($this->handle) == &quot;Unknown&quot; ) {
				return true;
		}
		return fclose($this->handle);
	}

うーんはたしてこの対処でいいのだろうか?fopenしたものはちゃんとcloseできているのか?
詳しい方だれか教えてください・・・。

comments powered by Disqus