[CakePHPのバグ]キャッシュ処理でunlinkエラーが発生する
CakePHP バージョン1系・バージョン2系でごくまれに次のようなエラーが出ることがあります。
ごくまれにしか発生しない現象で、気づきにくくリロードすると解消されるため調査・検証がしづらいです。
[参考記事] キャッシュ処理でunserializeエラーが発生する
Warning (2): unlink(/……/app/tmp/cache/models/cake_model_default_xxx) [http://php.net/function.unlink]: No such file or directory [CORE/cake/libs/file.php, line 298] Code unlink - [internal], line ?? File::delete() - CORE/cake/libs/file.php, line 298 FileEngine::clear() - CORE/cake/libs/cache/file.php, line 246 FileEngine::gc() - CORE/cake/libs/cache/file.php, line 104 Cache::_buildEngine() - CORE/cake/libs/cache.php, line 168 Cache::config() - CORE/cake/libs/cache.php, line 141 Configure::__loadBootstrap() - CORE/cake/libs/configure.php, line 436 Configure::getInstance() - CORE/cake/libs/configure.php, line 52 include - CORE/cake/bootstrap.php, line 38 [main] - …….php, line xxx
これはTMP cache models以下のデータベース用キャッシュファイルが同時アクセスでたまたま別アクセスで削除されたファイルを削除しようとした場合に発生します。
エラーが発生している箇所をたどっていくと次のようなコードになっています。
エラーの該当箇所付近
CORE/cake/libs/file.php, line 298
/**
 * Deletes the File.
 *
 * @return boolean Success
 * @access public
 */
	function delete() {
		clearstatcache();
		if (is_resource($this->handle)) {
			fclose($this->handle);
			$this->handle = null;
		}
		if ($this->exists()) {
			return unlink($this->path);
		}
		return false;
	}
clearstatcache()でファイルキャッシュを削除していますが、unlink()までに複数の処理があり同時にアクセスされた時にエラーが発生します。
次のように変更すると解消されます。
		if ($this->exists()) {
			return unlink($this->path);
		}
		   ↓
		if ($this->exists()) {
			return @unlink($this->path);
		}
ただし削除がされているにも関わらずfalseが戻ることがあるのでコードによっては障害となることがあります。
キャッシュ削除部分のコード
CORE/cake/libs/cache/file.php, line 246
/**
 * Delete all values from the cache
 *
 * @param boolean $check Optional - only delete expired cache items
 * @return boolean True if the cache was succesfully cleared, false otherwise
 * @access public
 */
	function clear($check) {
		if (!$this->_init) {
			return false;
		}
		$dir = dir($this->settings['path']);
		if ($check) {
			$now = time();
			$threshold = $now - $this->settings['duration'];
		}
		$prefixLength = strlen($this->settings['prefix']);
		while (($entry = $dir->read()) !== false) {
			if (substr($entry, 0, $prefixLength) !== $this->settings['prefix']) {
				continue;
			}
			if ($this->_setKey($entry) === false) {
				continue;
			}
			if ($check) {
				$mtime = $this->_File->lastChange();
				if ($mtime === false || $mtime > $threshold) {
					continue;
				}
				$expires = $this->_File->read(11);
				$this->_File->close();
				if ($expires > $now) {
					continue;
				}
			}
			$this->_File->delete();
		}
		$dir->close();
		return true;
	}
delete()の戻り値を見ていないのでキャッシュ削除では問題となりません。
CakePHPではアクセス数が多い場合の考慮がされていない部分がいくつかあります。
[参考記事] キャッシュ処理でunserializeエラーが発生する
関連記事
- 複数カラムのユニーク制約バリデーション
 - 標準のValidatorを拡張してカスタマイズする方法
 - テンプレート(template)側でログイン情報を取得する方法
 - フォームの必須エラーメッセージをHTML5標準にする方法、カスタマイズする方法
 - 標準のHelperを拡張してカスタマイズする方法 CakePHP2
 - 国際化i18n(多言語化)
 - URLをハイフン区切りからアンダーバー区切りやキャメルケースにする方法
 - CakePHP5系の入手方法・インストール方法
 - CakePHP4系の入手方法・インストール方法
 - CakePHP3系の入手方法・インストール方法
 - CakePHP2系の入手方法・インストール方法
 - CakePHP1系(CakePHP1.3)をPHP7・PHP8以降に対応させる方法
 - CakePHP1系(CakePHP1.3)の入手方法・インストール方法
 - Composerコマンドでウクライナへのメッセージが表示されたことがあります
 - Composerをインストールする方法と使い方
 - コーディング規約のチェックを行う・整形する標準ツール(PHP CodeSniffer)の使い方
 - Seedの実行順(外部キー制約などを先に実行させる方法) Foreign key violation
 - PostgreSQLでERROR: duplicate key value violates unique constraint "hoge_pkey" DETAIL: Key (id)=(10) already exists.と出る場合
 - PostgreSQLで自動採番をするシーケンス(sequence)とは【AUTO INCREMENT】
 - Apacheで所有権や書き込み権限があるにも関わらずPermissions deniedが出る場合
 - CakePHPのバージョンごとのシステム要件
 - 1つのフィールドにバリデーションエラーを1つだけ表示させる方法
 - PHP Strict Standards: Non-static method と出る場合の対処法
 - CakePHPでカラムを比較してSELECTする方法
 - 『id』以外のプライマリキーのカラム名を使用する方法
 - [CakePHPのバグ]キャッシュ処理でunserializeエラーが発生する
 - プライマリキーIDを連番数字ではなく推測しにくい文字列にする方法
 - 複数のデータベースを切り替える方法(別データベースを使用する)
 - MySQLで文字化けを防ぐ方法
 - action名にlistは使えない listを使う方法
 - ログイン認証処理をする方法
 - CakePHP、Symfony、Zend Frameworkの比較
 - CakePHPのDB接続情報設定
 - ファイル読み込みPATHを設定
 - デバッグレベルを設定
 - セキュリティレベルの設定
 - キャッシュを有効にする
 - CakePHPのエラーテンプレートの一覧
 - データベーステーブルを参照しないページを作る
 - TOPページはIndexControllerではない Cannot redeclare config()
 - ディレクトリ構成
 - CakePHP
 
スポンサーリンク





