世界線航跡蔵

Mad web programmerのYuguiが技術ネタや日々のあれこれをお送りします。

2009年05月08日

サーバープロセスにおけるRDフィルタ処理の同時実行問題

昨日から一時的に、記事とあまり関係なさそうな画像や他の記事の文章が脈絡もなく挿入されてカオスなことになる場合があった。アクセスログを見るには、たぶん、私以外の閲覧者の誰かがこの問題に遭遇している。うーん、お恥ずかしい。

これは自家製ブログシステム(rhianoletheと呼んでいる)のバグで、現在は解決している。サーバープロセスでRDtoolを用いてRDを整形するときにfilterの処理がプロセス間で衝突する問題だった。

事象

私はRDが好きだ。というわけで、このブログの原稿はRDで入力して、HTMLに変換している。ただし、古い記事の中にはHTMLでベタうちしてあるものもあるので、それらをRDtool経由で処理するためにRD::INCLUDE_FILTERを使ったりしている。また、幾つかの特殊なfilterを独自定義してRDの拡張として利用している。

ここで、RDtoolはfilterを処理するために一時ファイルを生成する。一時ファイルのファイル名にはプロセスIDを含めることで一意性を確保しているのだけれども、確保できていなかった。rdblockparser.tab.rbから該当部分を抜粋すると、こんな感じ。

class RDParser < Racc::Parser
module_eval <<'..end lib/rd/rdblockparser.ry modeval..idc4b57748f0', 'lib/rd/rdblockparser.ry', 231
include ParserUtility

TMPFILE = ["rdtmp", $$, 0]

....

      else # if output is target formated
        basename = TMPFILE.join('.')
        TMPFILE[-1] += 1
        tmpfile = open(@tree.tmp_dir + "/" + basename + ".#{@in_part}", "w")
        tmpfile.print(part_out)
        tmpfile.close
        subtree = parse_subtree(["=begin\n", "<<< #{basename}\n", "=end\n"])
      end
      .....

TMPFILE内に埋め込まれた$$の値はTMPFILE定義時に固定される。従って、rdblockparser.tab.rbを読み込んだ後にプロセスがforkして、かつそれらの子プロセスが並行して動くと一時ファイル名が衝突することがあり得る。こうして、子プロセス間でfilterの処理結果が上書きし合う結果になる。

影響される製品

この問題はRDtook付属のrd2コマンドでは発生しないと考えられる。基本的には、rd2コマンド実行中にforkが発生することはないと思われるためだ。一方、rhianoletheやRedmine rd formatterのようにサーバープロセス中でRD parserを呼んでいる場合は問題になり得る。幸いなことに、redmine_rd_formatterやその原型であるRedmine for rubyはfilterを使用していないので、バグは発現しない。

対応

この問題が、RD parserのバグなのかどうかは分からない。現在、作者のmoonwolfさんに問い合わせている。

とりあえずRD parserを使用する側でRDTree#tmpdirをプロセスごとに一意になるように設定して対応した。もしかすると、プロセスがforkする場合はRD parserはこう使うのが本当で、RD parserのバグではないのかもしない。

トラックバック

http://yugui.jp/articles/823/ping

現在のところトラックバックはありません

コメント

blog comments powered by Disqus

ご案内

前の記事
次の記事

タグ一覧

過去ログ

  1. 2016年07月
  2. 2016年01月
  3. 2015年09月
  4. 2015年08月
  5. 過去ログ一覧

フィード

フィードとは

その他

Powered by "rhianolethe" the blog system