ISAPI フィルターを作成しました。開発サーバーとSITサーバーで正常に動作します。
しかし、本番サーバーでは機能しません。
イベント ビューアーでは、次のログ:
キュー エラーの報告: アプリケーション w3wp.exe、バージョン 6.0.3790.2825、エラー モジュール msvcr80.dll、バージョン 8.0.50727.3053、エラー アドレス 0x00046039。
この問題に直面したとき、私はCodeProject からJochen Klambach の StackWalkerを入手しました。 更新: StackWalker は Codeplex に移行しました。間違いなくコードプレックスのリリースを入手してください。いくつかの更新と修正が含まれています。
フィルターがクラッシュすると、コードのスタックが出力されます。
私が行った方法は次のとおりです。フィルターの OnAuthComplete 内で、フィルターがすべての作業を行う場所で、ロジックを try...except で囲みました。
__try
{
dwRetval = DoRewrites(...);
}
__except ( ExcFilter(GetExceptionInformation()) )
{
}
そして、ExcFilter は次のように定義されます。
extern "C" int ExcFilter(EXCEPTION_POINTERS *pExp)
{
MyLoggingStackWalker *sw = new MyLoggingStackWalker();
sw->ShowCallstack(GetCurrentThread(), pExp->ContextRecord);
return EXCEPTION_CONTINUE_SEARCH; // allow the process to crash
}
LoggingStackWalker は StackWalker から派生し、OnOutput メソッドをオーバーライドしてその出力をログ ファイルに送信します。また、DLL が見つかったディレクトリを含むように PDB ファイルの検索パスを設定します。
class MyLoggingStackWalker : public StackWalker
{
public:
MyLoggingStackWalker() : StackWalker()
{
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
// add the directory for the ISAPI DLL, to the search path for PDB files
this->m_szSymPath = (LPSTR) malloc(_MAX_PATH);
_splitpath_s(DllLocation, drive, _MAX_DRIVE, dir, _MAX_DIR, NULL, 0, NULL, 0);
_makepath_s(this->m_szSymPath, _MAX_PATH, drive, dir, NULL, NULL);
}
virtual void OnOutput(LPCSTR szText)
{
LogMessage((char*)szText);
StackWalker::OnOutput(szText);
}
};
それを実証するために、コード内の vscprintf に不適切なポインターを渡します。IIS7 でのスタック トレースの結果は次のようになります。最初の数フレームが C ランタイムにあり、行番号も付いていることがわかります。(デフォルト設定を使用する場合、StackWalker は実際に MS シンボル サーバーからシンボル ファイルをダウンロードします。必要に応じてこれをオフにすることもできます。) 次に、フレームの次の束は私のコードからのものです。問題の場所を特定します。私の次のスタック フレーム - これらはすべて IIS モジュールです。これは Vista の IIS7 です。シンボル サーバーには、これらのモジュールのシンボルがなかったと思います。とにかく、スタックトレースを見ると、問題がどこにあるかは疑いの余地がありません。
f:\dd\vctools\crt_bld\self_x86\crt\src\output.c (1068): _output_l
f:\dd\vctools\crt_bld\self_x86\crt\src\vsprintf.c (405): _vscprintf_helper
f:\dd\vctools\crt_bld\self_x86\crt\src\vsprintf.c (414): _vscprintf
c:\dev\isapi\filter\logger.c (193): LogMessage
c:\dev\isapi\filter\rewriter.c (2036): EvaluateRewrites
c:\dev\isapi\filter\rewriter.c (789): DoRewrites
c:\dev\isapi\filter\rewriter.c (955): OnAuthComplete
c:\dev\isapi\filter\rewriter.c (1139): HttpFilterProc
60531896 module(filter): (filename not available): (function-name not available)
60531FAB module(filter): (filename not available): (function-name not available)
605314E3 module(filter): (filename not available): (function-name not available)
60531276 module(filter): (filename not available): (function-name not available)
6D122EA0 module(iiscore): (filename not available): (function-name not available)
6D123696 module(iiscore): (filename not available): (function-name not available)
6D12AA4C module(iiscore): (filename not available): (function-name not available)
6D125D3B module(iiscore): (filename not available): (function-name not available)
6D1220F4 module(iiscore): (filename not available): (function-name not available)
6D124EEF module(iiscore): (filename not available): (function-name not available)
6D12C6B8 module(iiscore): (filename not available): (function-name not available)
70CB13B3 module(w3dt): (filename not available): UlAtqGetContextProperty
70CB11DA module(w3dt): (filename not available): (function-name not available)
71A42611 module(W3TP): (filename not available): THREAD_POOL::PostCompletion
71A42812 module(W3TP): (filename not available): OverrideThreadPoolConfigWithRegistry
71A41E85 module(W3TP): (filename not available): (function-name not available)
76A54911 module(kernel32): (filename not available): BaseThreadInitThunk
7727E4B6 module(ntdll): (filename not available): __RtlUserThreadStart
7727E489 module(ntdll): (filename not available): _RtlUserThreadStart
7727E489 module(ntdll): (filename not available): _RtlUserThreadStart
まあ、何が起こっているかを伝えるのに十分な情報がここにはありません。本当に理解する必要があるのは、どのような条件が問題を引き起こしているかということです。ここでは、Windows 用の古き良きデバッグ ツールが役に立ちます。デバッガーの使用に慣れていない場合は、ADPlusやDebug Diagなどのツールが役立ちます。また、IIS 内でのデバッグに関するアドバイスを探している場合は、優れたリソースであるTess Ferrandez のブログも参照してください。
何かが無効なポインターを C ランタイム関数の 1 つに渡している可能性があります。デバッガーを使用すると、その関数が何であるか、および渡される引数が何であるかを識別できるはずです。うまくいけば、その情報で武装して、何が起こっているのかを理解できるようになるでしょう.
プロセスにアタッチし、VisualStudioを使用してデバッグできるはずです。Process Explorerを使用して、dllを実行しているw3wp.exeプロセスを特定し、リモートデバッグツールを使用して、別のマシンでコードをデバッグできるようにすることができます。