ファイルロック解除処理
またもPHPでの排他処理について。ファイルに書き込みを行う場合は
$fp = fopen('data.txt', 'r+') or exit('error!');
flock($fp, LOCK_EX);
~ここで書き込みを行う~
flock($fp, LOCK_UN);
fclose($fp);
で問題ないと思ったけど、まだ駄目っぽい。ロックの解除に問題があり、ファイルの破損は完全に回避できないらしい。調べてみると色々出てきた。
fcloseの前にflock(ファイルポインタ, LOCK_UN) する人は実に多いのですが、これははっきりと間違いだと断言します。flockをfcloseの前に解除するということは、fcloseの前に他のプロセスが割り込む可能性が出るということです。ファイルへの書き込みは、fwriteとかfputsとかしてからfflushまたはfclose実行までのどこかで行われる、というのがファイル周りのI/Oの基本です。なので、fcloseもロックの範囲内に入れなければなりません。fcloseでflockが解除されるのはそういう理由があるのです。
PHP/ファイルロック/設計 - TestWiki - PukiWiki Plus!
プロセスレベルの書き込みバッファによって、書き込みデータがOSに渡されずに残っている可能性がある。
fflush($fp); flock($fp, LOCK_UN); fclose($fp);
で明示的にフラッシュするか、flock($fp,LOCK_UN)しないで
fclose($fp); // LOCK_UN してはならない
をすることで、バッファがフラッシュされた後、ロックが解除される。
ロックの解放には fclose() でを使用します (これは、スクリプトが終了した場合にも自動的にコールされます)。
公式サイトの解説は「ロックの解放には fclose() でを使用します」と書いている割に、サンプルコードでは flock($fp, LOCK_UN);
で解除しています。こんな風に書かれていたら、どっちでも大丈夫なのかと思ってしまうよ…。
公式サイトのサンプルコードは、あまり信用しないほうがいいのかなぁ…。公式サイトなのに。
ついでに書くと「でを使用します」って誤字ですよね…?
ともかく、ロックの解除は fclose()
にまかせて
$fp = fopen('data.txt', 'r+') or exit('error!');
flock($fp, LOCK_EX);
~ここで書き込みを行う~
fclose($fp);
が正しいっぽい。