Skip to content

in Grijjy.ErrorReporting.pas we can not get the stacktrace report of a particular exception we catch in try... except end #3

@Zeus64

Description

@Zeus64

in Grijjy.ErrorReporting.pas we can not get the stacktrace report of a particular exception we catch in try... except end. I mean their is no way in a try .. except block to do something like MyReport := BuildExceptionReport(...), the only way is to catch the report in the event message. To handle this i updated the function below :

procedure TgoExceptionReporter.ReportException(const AExceptionObject: TObject;
  const AExceptionAddress: Pointer);
var
  E: Exception;
  ExceptionMessage: String;
  CallStack: TgoCallStack;
  ExceptionLocation: TgoCallStackEntry;
  Report: IgoExceptionReport;
  I: Integer;
begin
  { Ignore exception that occur while we are already reporting another
    exception. That can happen when the original exception left the application
    in such a state that other exceptions would happen (cascading errors). }
  if (FReportingException) then
    Exit;

  FReportingException := True;
  try
    CallStack := nil;
    if (AExceptionObject = nil) then
      ExceptionMessage := 'Unknown Error'
    else if (AExceptionObject is Exception) then
    begin
      E := Exception(AExceptionObject);
      ExceptionMessage := E.Message;
      if (E.StackInfo <> nil) then
      begin
        CallStack := GetCallStack(E.StackInfo);
        for I := 0 to Length(Callstack) - 1 do
        begin
          { If entry in call stack is for this module, then try to translate
            the routine name to Pascal. }
          if (CallStack[I].ModuleAddress = FModuleAddress) then
            CallStack[I].RoutineName := goCppSymbolToPascal(CallStack[I].RoutineName);
        end;
      end;
    end
    else
      ExceptionMessage := 'Unknown Error (' + AExceptionObject.ClassName + ')';

    ExceptionLocation.Clear;
    ExceptionLocation.CodeAddress := UIntPtr(AExceptionAddress);
    GetCallStackEntry(ExceptionLocation);
    if (ExceptionLocation.ModuleAddress = FModuleAddress) then
      ExceptionLocation.RoutineName := goCppSymbolToPascal(ExceptionLocation.RoutineName);

    Report := TgoExceptionReport.Create(ExceptionMessage, ExceptionLocation, CallStack);
    try
      TMessageManager.DefaultManager.SendMessage(Self,
        TgoExceptionReportMessage.Create(Report));
    except
      { Ignore any exceptions in the report message handler. }
    end;
  finally
    FReportingException := False;
  end;
end;

and i replace it by this one :

function TgoExceptionReporter.internalBuildExceptionReport(const AExceptionObject: TObject; const AExceptionAddress: Pointer): IgoExceptionReport;
var
  E: Exception;
  ExceptionMessage: String;
  CallStack: TgoCallStack;
  ExceptionLocation: TgoCallStackEntry;
  I: Integer;
begin

  CallStack := nil;
  if (AExceptionObject = nil) then
    ExceptionMessage := 'Unknown Error'
  else if (AExceptionObject is Exception) then
  begin
    E := Exception(AExceptionObject);
    ExceptionMessage := E.Message;
    if (E.StackInfo <> nil) then
    begin
      CallStack := GetCallStack(E.StackInfo);
      for I := 0 to Length(Callstack) - 1 do
      begin
        { If entry in call stack is for this module, then try to translate
          the routine name to Pascal. }
        if (CallStack[I].ModuleAddress = FModuleAddress) then
          CallStack[I].RoutineName := goCppSymbolToPascal(CallStack[I].RoutineName);
      end;
    end;
  end
  else
    ExceptionMessage := 'Unknown Error (' + AExceptionObject.ClassName + ')';

  ExceptionLocation.Clear;
  ExceptionLocation.CodeAddress := UIntPtr(AExceptionAddress);
  GetCallStackEntry(ExceptionLocation);
  if (ExceptionLocation.ModuleAddress = FModuleAddress) then
    ExceptionLocation.RoutineName := goCppSymbolToPascal(ExceptionLocation.RoutineName);

  result := TgoExceptionReport.Create(ExceptionMessage, ExceptionLocation, CallStack);

end;

procedure TgoExceptionReporter.ReportException(const AExceptionObject: TObject;
  const AExceptionAddress: Pointer);
var
  Report: IgoExceptionReport;
begin
  { Ignore exception that occur while we are already reporting another
    exception. That can happen when the original exception left the application
    in such a state that other exceptions would happen (cascading errors). }
  if (FReportingException) then
    Exit;

  FReportingException := True;
  try

    Report := internalBuildExceptionReport(AExceptionObject, AExceptionAddress);
    try
      TMessageManager.DefaultManager.SendMessage(Self,
        TgoExceptionReportMessage.Create(Report));
    except
      { Ignore any exceptions in the report message handler. }
    end;
  finally
    FReportingException := False;
  end;
end;

class function TgoExceptionReporter.BuildExceptionReport(const AExceptionObject: TObject; const AExceptionAddress: Pointer): IgoExceptionReport;
begin
  if Assigned(FInstance) then
    result := FInstance.internalBuildExceptionReport(AExceptionObject, AExceptionAddress)
  else
    result := nil;
end;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions