* スキンファイルの中でdie_message()を呼ぶとループが発生する (MenuBarに設置された任意のプラグインが die_message() を呼ぶとループが発生する) [#qdcfaead]

-ページ: [[BugTrack2]]
-投稿者: [[henoheno]]
-優先順位: 普通
-状態: 提案
-カテゴリー: 本体バグ
-投稿日: 2005-02-26 (土) 14:34:26
-バージョン: 

** 修正 [#s7ba7866]
- [[cvs:plugin/counter.inc.php]] (1.16) die_message()ではなくdie()を使用する
- [[cvs:lib/file.php]] (1.22) die_message()ではなくdie()を使用する

** 関連 [#u6ab84b8]
- [[BugTrack/768#nf12a652]]: XHTML1.0 時、colorプラグインで bgcolorを指定するとUsageが表示される -- pkwk_output_dtd() already called. Why?
- [[official:続・質問箱/614]]: "pkwk_output_dtd() already called. Why?"というエラー

** メッセージ [#z5ed6262]
スキンファイルの中で die_message() をコールした場合、また、MenuBarのページにプラグインを設置した場合、それがきっかけで以下のようなエラーが表示されることがあります。
- "pkwk_output_dtd() already called. Why?" (※pkwk_output_dtd()を二度コールしたとき)
- Headers already sent at /path/to/pkwk/lib/html.php line 425. (※ pkwk_headers_sent() を二度コールしたとき。示されている行はpkwk_output_dtd()の内部)

** 概要 [#rfda2d0e]
+ スキンファイルの中で呼ばれる関数 pkwk_output_dtd() は、絶対に一度しか呼ばれない関数であるため、二度目に呼んだ時には "pkwk_output_dtd() already called. Why?" というエラーを表示し、スキンファイルにまつわる異常な処理があることを間接的に知らせます。
+ die_message()の現在の仕様上、スキンファイルの中でコールすると、結果的に catbody() 関数を再帰的に呼び出すループが発生します。
-- 代わりにdie()を使わねばなりません。
+ MenuBarの処理はスキンファイルの中で行われています。
+ 個々のプラグインは、基本的にそれがMenuBarで実行されるのか、本文で実行されるのかをいちいち考慮しません。(一部の例外: includeプラグイン)
+ counterプラグインは、その用途上 MenuBar のページに設置されます。
+ counterプラグインは、counter周りのファイルに書き込みができない場合に die_message() をコールします。

MenuBarのページにcounterプラグインを設置する => 再表示しようとする => スキンファイルの処理開始 => pkwk_headers_sent() や pkwk_output_dtd() がコールされる => MenuBarのページが、スキンファイルの内部で処理される => counterディレクトリ周りの書き込み権限がないことをcounterプラグインが見つける => counterプラグインが die_message() をコール => die_message() のループが成立する => pkwk_output_dtd() あるいは pkwk_headers_sent() がもう一度コールされる => "pkwk_output_dtd() already called. Why?" といったエラーだけが表示される => 原因がわからず、ユーザーは困惑する

※counterプラグインに限った話ではありません

----
-特に counter ディレクトリ周りに書き込み権限が無いときに、counterプラグインを MenuBar に設置すると "pkwk_output_dtd() already called. Why?" と表示されますが、これはつまるところ die_message() の問題であるようです。 -- [[henoheno]] &new{2005-02-26 (土) 14:40:12};
-counterプラグインからdie_message()を取り除くのは、対症療法としては有効ですが完全ではありません。 -- [[henoheno]] &new{2005-02-26 (土) 14:43:39};
-PukiWiki 1.4.5_1 では、原因は変わりませんが、 pkwk_headers_sent() が多重にコールされる結果違うエラーメッセージ(上記に追加)が表示されるようです。 -- [[henoheno]] &new{2005-02-26 (土) 15:19:19};
-ひとまずcounterプラグインはMenuBarに設置される事が多いですから、die_message()を使わないように修正しました。 -- [[henoheno]] &new{2005-04-09 (土) 12:10:15};
-いずれにせよcounterプラグインだけの問題ではありませんから、何かフラグを設けてdie_message()が既に実行されたかどうかを判定する必要がありそうです。 -- [[Ratbeta]] &new{2005-04-23 (土) 12:31:51};

- [[BugTrack2/262]] で出力開始前にMenuBar の処理をするようになったおかげで、発生確率が減った?((他の直書きプラグインの挙動を確認する必要はあるでしょう)) --  &new{2008-03-21 (金) 22:20:49};

- 気になった点をいくつか書き連ねます。 --  &new{2009-04-14 (火) 18:03:39};
-- 今のlib/func.php (1.102) のdie_message() は、catbody() を実行する場合とexit する場合のどちらでも pkwk_common_headers() を実行していますが、これは意味があるのでしょうか?&br;各スキンファイルがpkwk_common_headers() を呼び出すかを判断している((というか、携帯用のスキンでは呼び出してないだけ?))ので、catbody() を実行する場合はpkwk_common_headers() を呼び出す必要が無いと思います。 --  &new{2009-04-14 (火) 18:03:39};
-- 既に実行されたかを判断するフラグだけだと、「初めてdie_message() を呼び出した時点ですでにヘッダーを出力している場合((例えば、スキンに直接書いた部分が原因で、ヘッダーの出力後に呼び出される場合))」には対応できないので、最初にheaders_sent() でチェックしてから、フラグ込みでcatbody() を実行するかを判断((改造に失敗しないと起こらないと思いますが、ヘッダーが出力されていない状態でcatbody() → die_message() → catbody() → 以降ループ、となる場合を回避するため))したほうがいいと思います。 --  &new{2009-04-14 (火) 18:03:39};
-- 追記: よくよく考えると、MenuBar の処理をヘッダー出力の前に行うスキンを使う場合、MenuBar 内でdie_message() を呼ぶ状況に陥るとループが成立するかもしれませんね・・・ --  &new{2009-04-15 (水) 00:42:22};
--- ふむ、MenuBarについてはタイトルで触れてある通りのようですね。 -- [[henoheno]] &new{2009-04-18 (土) 09:49:22};
--- ふむ、MenuBarについてはタイトルで触れてあるのと似たシチュエーションのようですね (^^; -- [[henoheno]] &new{2009-04-18 (土) 09:49:22};

#comment

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Site admin: PukiWiki Development Team

PukiWiki 1.5.3+ © 2001-2020 PukiWiki Development Team. Powered by PHP 5.6.40-0+deb8u12. HTML convert time: 0.059 sec.

OSDN