2011-12-15 14 views
4

Bob Swartのホワイトペーパーを参考にして、Datasnapサービス(Delphi XE)を作成しました。それは正常に動作し、私たちはテストサーバーにそれを配備しました。処理された/捕らえられた例外からスタックトレースを取得してトレースログにダンプする方法

多くのリクエスト(JMeter経由)を実行すると、何らかの種類のメモリ破損が発生するという問題が発生しました。一部の要求は成功し、一部はアクセス違反で失敗します。結局、それは私たちのOWN(DSAdminではない)メソッドに対するすべての要求がアクセス違反で応答するように、非常に壊れています。

しかし、例外処理がリクエストの処理中にすでにキャッチされているため、スタックトレースに手を入れて情報を取得できません。

このアプリケーションのVCLバージョンで大きくテストすると、正しく動作します。

これは何か、あるいは同じ問題を経験したことのある人がいますか?またはキャッチされた例外(ほかの誰かのコードで編集できないもの)からスタックトレースを取得できますか?

ありがとうございます。

+1

[MadExcept](http://madshi.net/madExceptDescription.htm)や[Open Source unit](http://blog.synopse.info/post/2011/04)のような例外ハンドラを追加することができます。/14/Enhanced-logging-in-SynCommons))を実行して、実行中にスタックトレースを取得します。このスタックトレースでは、根本的な原因を見つけることは不可能です。ロギングを追加すると、サービスのデバッグに多くの助けになります。 –

+2

はい捕獲された例外にスタックトラックを記録することができます。 JEDIクラスライブラリからJclDebugを入手し、あなたのアプリに追加してください。「処理された/捕らえられた例外からスタックトレースを取得してトレースログにダンプする方法」に質問を編集した場合、私は喜んで回答などの投稿を行います。私はそのテクニック(トレースログ+ JCLデバッグ)を何度も使用して、サービスクラッシュをデバッグしました。 –

+0

競合状態が発生しているようです。 あなたはスレッドの安全性を考えましたか? – whosrdaddy

答えて

7

JEDI JCLを使用してキャッチされた例外とキャッチされない例外の両方をログに記録するには、JEDI JCLをインストールする必要があります。その後

jcl\examples\windows\debug\framestrack\FramesTrackDemoMain.pasから取られたこのコードのようないくつかのコードを試してみてください。

これが機能するためにあなたは、コンパイラおよびあなたのデルファイプロジェクトオプションでリンカオプションの両方での完全なデバッグ情報でコンパイルする必要があります。

LogExceptionを呼び出す必要はありません。例外通知コールバック(JclAddExceptNotifier)を追加したものが自動的に呼び出されます。あなたがからそれを追加しているフォームまたはデータモジュールが破壊されたときに、ここで示したように、またJclRemoveExceptNotifierを呼び出すことを忘れないでください:

procedure TForm1.LogException(ExceptObj: TObject; ExceptAddr: Pointer; IsOS: Boolean); 
var 
    TmpS: string; 
    ModInfo: TJclLocationInfo; 
    I: Integer; 
    ExceptionHandled: Boolean; 
    HandlerLocation: Pointer; 
    ExceptFrame: TJclExceptFrame; 

begin 
    TmpS := 'Exception ' + ExceptObj.ClassName; 
    if ExceptObj is Exception then 
    TmpS := TmpS + ': ' + Exception(ExceptObj).Message; 
    if IsOS then 
    TmpS := TmpS + ' (OS Exception)'; 
    mmLog.Lines.Add(TmpS); 
    ModInfo := GetLocationInfo(ExceptAddr); 
    mmLog.Lines.Add(Format(
    ' Exception occured at $%p (Module "%s", Procedure "%s", Unit "%s", Line %d)', 
    [ModInfo.Address, 
    ModInfo.UnitName, 
    ModInfo.ProcedureName, 
    ModInfo.SourceName, 
    ModInfo.LineNumber])); 
    if stExceptFrame in JclStackTrackingOptions then 
    begin 
    mmLog.Lines.Add(' Except frame-dump:'); 
    I := 0; 
    ExceptionHandled := False; 
    while (chkShowAllFrames.Checked or not ExceptionHandled) and 
     (I < JclLastExceptFrameList.Count) do 
    begin 
     ExceptFrame := JclLastExceptFrameList.Items[I]; 
     ExceptionHandled := ExceptFrame.HandlerInfo(ExceptObj, HandlerLocation); 
     if (ExceptFrame.FrameKind = efkFinally) or 
      (ExceptFrame.FrameKind = efkUnknown) or 
      not ExceptionHandled then 
     HandlerLocation := ExceptFrame.CodeLocation; 
     ModInfo := GetLocationInfo(HandlerLocation); 
     TmpS := Format(
     ' Frame at $%p (type: %s', 
     [ExceptFrame.ExcFrame, 
     GetEnumName(TypeInfo(TExceptFrameKind), Ord(ExceptFrame.FrameKind))]); 
     if ExceptionHandled then 
     TmpS := TmpS + ', handles exception)' 
     else 
     TmpS := TmpS + ')'; 
     mmLog.Lines.Add(TmpS); 
     if ExceptionHandled then 
     mmLog.Lines.Add(Format(
      '  Handler at $%p', 
      [HandlerLocation])) 
     else 
     mmLog.Lines.Add(Format(
      '  Code at $%p', 
      [HandlerLocation])); 
     mmLog.Lines.Add(Format(
     '  Module "%s", Procedure "%s", Unit "%s", Line %d', 
     [ModInfo.UnitName, 
     ModInfo.ProcedureName, 
     ModInfo.SourceName, 
     ModInfo.LineNumber])); 
     Inc(I); 
    end; 
    end; 
    mmLog.Lines.Add(''); 
end; 


procedure TForm1.FormCreate(Sender: TObject); 
begin 
    JclAddExceptNotifier(Form1.LogException); 
end; 

procedure TForm1.FormDestroy(Sender: TObject); 
begin 
    JclRemoveExceptNotifier(Form1.LogException); 
end; 

これは、通常の初期化コードです:

initialization 

    JclStackTrackingOptions := JclStackTrackingOptions + [stExceptFrame]; 
    JclStartExceptionTracking; 

はここですJCL FramesTrackExample.dprojデモ実行:あなたの目的のために

enter image description here

に、TMemo.Linesに行を追加するコードを変更します代わりにディスク上のログファイルに書き込みます。すでにロギングシステムをお持ちの場合はそれが素晴らしいですし、そうでない場合はLog4Dと考えてください。

+0

感謝。私は明日それを調べることができることを願っています、最近はちょっと忙しいです。 – Geerten

+0

ありがとう、私はそれを働かせました! ExceptFrame.ExcFrameはExceptFrame.FrameLocationです。(提供したリンクの最新のダウンロードでこれが見つかりました) – Geerten

+0

JCLデバッグは最後に見てからちょっと微調整されていると思います。 –

-1

すべての新しいWebサービスコールは新しいスレッドです。一部のリソースは、次のサービスコールが来て新しいスレッドがそれらにアクセスしようとすると、前のスレッドによって割り当てられます。また、別のスレッドがそれらを使用しようとしたときに、あるスレッドがリソースを解放することもあります。 TCriticalSectionを使用して、すべてのリソースが1つのスレッドに対してのみ使用可能であることを確認する必要があります。また、TCriticalSectionがグローバル変数であり、すべてのインスタンスからアクセス可能であることを確認してください。

+0

グローバルリソースを使用しないでください。質問自体に関する私のコメントで述べたように、スレッドセーフではないコードの問題ではありません。 – Geerten

+0

この非常に一般的なアドバイスは、この質問をした人には当てはまりません。あなたは助けになろうとしていますが、彼の特別な事例に少なくとも適用される具体的な詳細な指示がないので、私はダウン投票しました。 (何かをグローバルにしているのか、そうでないのか? –

関連する問題