雑記

思ったこと、あれこれ・・・

2003-02-04

排他制御

うちのサイト内に設置してある『トレセン』というCGIゲームですが、(昨年の今頃に)突然『ユーザリストが飛ぶ』というハプニングが頻発するようになりました。
突然頻発し始めた理由は不明ですが、CGIのログファイル(データファイル)が飛ぶ原因は『ファイルへの複数同時書き込み』に他なりません。
『トレセン』の場合IDとパスの認証を『各プレイヤーのデータファイル』では無く『ユーザリストファイル』の読み込みによって行っている為、ユーザリストが飛ぶと誰もログインできなくなり、かなり『致命的』なのです。

通常CGIプログラムのスクリプトにはこの『同時書き込み』を防ぐ為の『ファイルロック(排他制御)』というプログラムが組み込まれています。
排他制御とはつまり、複数が同時に同じファイルにアクセスしようとした場合に『これから私が書き込むから、他の誰も読んだり書いたりしないでね!』と宣言し、一人が書き込んでいる間は他の誰も書き込みができないようにするプログラムです。
ユーザリストが飛ぶというのは、この『排他制御』に問題があるということ。

そこで調査に乗り出しました。


トレセンのスクリプトの元はフリーで配付されているものですが、まずはこのスクリプトに組み込まれている排他制御のサブルーチンを調べてみたところ、いちおう排他制御用のサブルーチンは組み込まれているようです。
では、何が問題なのか・・・?

そして2、3日かけて色々調べているうち『排他制御』について多くの事を学ぶ結果となったわけです。


まず、トレセンの当初のスクリプトはopen関数を使用した排他制御でした。
これは擬似的に排他処理を行うものの、ロック不全を起こす『穴』があることが判明。
簡単に説明すると、この方法では『ロックの判定』と『ロックの作成』が1処理で行われない為、Aさんのタスク(スクリプト実行)でロック判定が『可』と判定されてからロックを作成する僅かな時間にBさんのタスクでもロックが『可』と判定されてしまう可能性があるのです。
そうなると、AさんとBさんのメイン処理が重なってデータファイル破損という事態に・・・。

ちゃんとした排他処理を行うには、『ロック判定』と『ロック作成』を1処理で行える関数:flock / symlink / mkdr 等を使用すべきだったのです。
ただsymlinkやmkdrを使用した場合、スクリプトが異常終了してロックが解除されずに残ってしまうことがあり、その残留ロックを解除するプログラム上でどうしても同時書き込みを可能にしてしまう『穴』ができてしまうようです。
ゆえに、最も確実な方法はflock関数を用いた処理となります。

ただしflockやsymlink関数は使用しているサーバーのOSやperlのバージョンによっては使用できないところもあり、使用できないサーバーでこれを実行するとサーバーが『致命的なエラー』を起こしてしまうことがあるそうです。
(特に、共用サーバーがダウンしてしまったら自分だけの問題では無くなってしまいますからね)
また、実装していても実際に動作しないサーバーもあるらしいので、いずれにせよ使用する際にはサーバー管理者に確認をとったほうがいいでしょう。

で、私の使用サーバーは幸いにもflock関数が使用OKということを確認。
(むしろ、排他制御にはflock関数を推奨とのこと)

というわけで、トレセンの排他処理をflock関数を用いた処理に書き換えることにしました。

あと、当たり前のことですが・・・
いくら確実な関数を使っていても、スクリプト上でそのサブルーチンを呼び出す場所が正しくなければ台無しになってしまいます。
例えば

読み込みオープン
 ↓読み込む
クローズ
いろいろな処理
【ロック】
書き込みオープン
 ↓書き込む
クローズ
【アンロック】

なんて順序では、せっかくの排他制御も無意味になってしまう、ということです。
上記は

【ロック】
読み込みオープン
 ↓読み込む
クローズ
いろいろな処理
書き込みオープン
 ↓書き込む
クローズ
【アンロック】

というように、ファイルを読み込んで書き換えるまでの処理を『ロックされている間』に一気にやってしまわなくてはならないのです。

トレセンのスクリプトはopen関数を使用していただけでなく、この点でもひっかかっていました。
そこでこれを機会に私が使用しているフリー配付のCGIを全て見直してみたのですが、驚いたことにきちんと排他処理を実行できているスクリプトは数えるほどしかありませんでした。(^^;)
それだけではありません、注意書きもなくハナからflock関数やsymlink関数を使用しているCGIも幾つかあったのです。(マジで)


というわけで、
今までログデータが飛んでしまったり致命的エラーを起こさずにCGIを運用できていた私は、ただ単にラッキーなだけだったようです。(^^;)

いやいや、勉強になりました。


(※ flockが使えないサーバーでも、symlinkやmkdrとrenameを併用することで完全な排他を実現することは可能なようですが、スクリプトがやや複雑になってしまうようです・・・)

(02:30:00) ‖ Category: PC Work

Comments


Forexbliday
At lære forexhandel online. https://dk.forex-stock-bitc...
2022-04-19 (15:52:39)


Add Comments












TrackBack


(この記事へのトラックバックはありません)



トラックバックURL:
※ あなたのブログがトラックバック送信に対応していない場合はこちらからトラックバックを送信できます。



この記事へのリンクが無い記事は、トラックバックできません。
《この記事のURL》http://limelight.sakura.ne.jp/blog/index.php?itemid=5