* * *

Author Topic: Handling exceptions in Lazarus applications  (Read 3839 times)

runner

  • New member
  • *
  • Posts: 6
Handling exceptions in Lazarus applications
« on: September 02, 2010, 04:52:39 pm »
Hi,

I come from Delphi enviroment and there I have logging and exception handling well taken care of. I use JCL for exception handling and my own solution for logging. I can get stack trace for handled and unhandled exceptions (hooks every exception in the app) or just unhandled exceptions. What is the best way to do this in Lazarus.

I know there is Application.OnException. The problems I see are:

1. Will this handle DLL exceptions and exceptions not directly associated with application code, but still running inside application memory space? I would say no.
2. How to get stack trace with function names and source code line numbers. I know how to get stack trace, but no matter what I do, when I call it from inside Application.OnException I only get the addresses (yes I have -gl linker option set). I tried everything to no avail.

How do you solve this. Something as important as this must have a simple solution. I read the forums and wiki but I cannot find some solid information to solve this problem I have. So sorry if it is simple and obvious. Usually I serch for solutions myself.

The other thing I want to know is, are there any good logging solutions for Lazarus out there?

Thank you very much for your help :)
« Last Edit: September 02, 2010, 04:55:13 pm by runner »

chronos

  • Jr. Member
  • **
  • Posts: 70
    • PascalClassLibrary
Re: Handling exceptions in Lazarus applications
« Reply #1 on: September 02, 2010, 09:09:19 pm »
This is indeed important topic. I have just written some information collected from forum to wiki page. Not completed yet but everyone can add useful information. http://wiki.freepascal.org/Logging_exceptions

There should be some answers to your questions somewhere. We have make enough effort to find out.

To get exception info:
Thread id
Exception class
Exception message

To get stacktrace with:
Unit name
Address
Function name
Source code line number
Parameter values...

runner

  • New member
  • *
  • Posts: 6
Re: Handling exceptions in Lazarus applications
« Reply #2 on: September 02, 2010, 09:44:51 pm »
@chronos

Thank for the link and the contribution. I made some more tests and can now confirm what I read in the forums.

1. If I catch the exception on the spot (in the flow of the executing code) I get the function names and line numbers
2. If I try to get stact trace from Application.OnException I do not get that, only the addresses. I do not understand fully why is that so.

I used "DumpExceptionBackTrace" in both cases. So my question remains. Ho do you manage application wide exception handling. This is a very important topic because it is essential to any error reporting in production applications. I do not see how you can assure quality without that.

Again thanks for help and clarifications.

chronos

  • Jr. Member
  • **
  • Posts: 70
    • PascalClassLibrary
Re: Handling exceptions in Lazarus applications
« Reply #3 on: September 04, 2010, 12:22:42 am »
After some more digging deeper I was able to modify unit lineinfo as CustomLineInfo and redirect function variable BackTraceStrFunc to fixed StabBackTraceStr.

Reason why no line info is displayed in OnException handler is that error occur in unit lineinfo function OpenStabs for particular not valid address which result to set static variable staberr to true and disable further GetLineInfo usage. I will post patch to bugtracker later.

I created some demo application(attached file) which you can test. Exception call stack is displayed properly in OnException handler. You can compare content of CustomLineInfo.pas file against FPC source lineinfo.pp with diff.

In demo stacktrace is returned as structured data so it is possible to display it to TListView nicely, create single line string report or log to text file.

FabienWang

  • Sr. Member
  • ****
  • Posts: 420
  • Laz Laz Laz
    • The open source man
Re: Handling exceptions in Lazarus applications
« Reply #4 on: September 04, 2010, 08:36:39 am »
I have this error when trying to compile chronos:

Stream=TMainForm: Root=:TMainForm
Component Class: TListView
Error reading ListView1.ItemIndex: Unknown property: "ItemIndex"
Stream position: 1534

then it can't compile
FabienWang is using Arch Linux.
Projects: CPickSniff, OpenGrabby, LazPaint

chronos

  • Jr. Member
  • **
  • Posts: 70
    • PascalClassLibrary
Re: Handling exceptions in Lazarus applications
« Reply #5 on: September 04, 2010, 09:07:18 am »
Oh, I have some trunk version Lazarus 0.9.29 rev. 27261 with FPC 2.4.0. This kind of error you have on opening project I guess. Lazarus should guide you to remove non existed properties from lfm. You can remove it directly from lfm file too. Maybe I should have stable version 0.9.28 aside...

runner

  • New member
  • *
  • Posts: 6
Re: Handling exceptions in Lazarus applications
« Reply #6 on: September 05, 2010, 11:01:59 am »
@chronos

Thanks for your help. I will check your code and changes.

I have find a workaround in the meantime. If you specify this as the Application flag:

Include(Application.Flags, AppNoExceptionMessages);

, then it works. I have looked at how the Application class handless messages and yes it handles them first:

 
Code: [Select]
if not (AppNoExceptionMessages in FFlags) then
  begin
    // before we do anything, write it down
    if ExceptObject is Exception then
    begin
      if not Skip then
      begin
        DebugLn('TApplication.HandleException ',Exception(ExceptObject).Message);
        DumpExceptionBackTrace;
      end;
    end else
    begin
      DebugLn('TApplication.HandleException Strange Exception ');
      DumpExceptionBackTrace;
    end;
  end;

Here the BackTrace is dumped to stdout and because for unknown reasons to me only the first dump works this spoils the OnException handler.

Ok I have this sort of under control. The other things is what to do if I want to handle exception that are not handled by the Application class. There is "exceptproc" that you can use, but as soon as Application class is initialized and run I do not recieve exceptions anymore in my handler. Is this a bug or intentional?

In my opinion the whole exception handling in Lazarus is not done in a very good and transparent way. I am impressed with Lazarus otherwise and appreciate the hard work being done here. But I feel that this is so important topic, that it should get more attention. You just cannot have a production deployed application without a clean stack trace logging on exceptions. And also all unhandled exceptions must be logged no matter where they came from as long as they originate from the same process address space.

Maybe I am still missing something?

chronos

  • Jr. Member
  • **
  • Posts: 70
    • PascalClassLibrary
Re: Handling exceptions in Lazarus applications
« Reply #7 on: September 05, 2010, 12:46:37 pm »
But exception logging is only for development and testing purpose. You don't want do distribute your release version with debug information and have 40 MB exe file instead of 4 MB. Debug information can be useful for reverse engineering too. Then included debug information and stack trace could be good for beta testers to get useful bug report from them.

TApplication class contains method which replace default ExceptProc initialized by InitExceptions in SysUtils unit.

Code: [Select]
procedure TApplication.SetCaptureExceptions(const AValue: boolean);
begin
  if FCaptureExceptions=AValue then exit;
  FCaptureExceptions:=AValue;
  if FCaptureExceptions then begin
    // capture exceptions
    // store old exceptproc
    if FOldExceptProc=nil then
      FOldExceptProc:=ExceptProc;
    ExceptProc:=@ExceptionOccurred;
  end else begin
    // do not capture exceptions
    if ExceptProc=@ExceptionOccurred then begin
      // restore old exceptproc
      ExceptProc:=FOldExceptProc;
      FOldExceptProc:=nil;
    end;
  end;
end;

runner

  • New member
  • *
  • Posts: 6
Re: Handling exceptions in Lazarus applications
« Reply #8 on: September 05, 2010, 01:02:35 pm »
@chronos

Ah I see. I will know where to look now for ExceptProc ;)

About debug info in production enviroment I dissagree. If in production you application crashes, how will you get the needed info where and why it crashed. This is so much true if this happens "randomly". All my Delphi application have stack trace logging on unhandled exceptions.
I am only referring to unhandled exceptions here. And all apps have bugs :) Also a lot of my products are server side code. So I am not worried about dissasembly.

I also now know how to create a map file with objdump. For stripped 4MB executable I only get around 4MB map file with all function names and addresses. But the addresses are slightly off. Do you maybe know why.

For instance I get an adress "$0829CB44" from "DumpExceptionBackTrace" and I have "$0829cb20" inside the dumped map file. If I can sort this out I can make a logging solution that would use such map files (maybe even compressed). So I would be very gratefull for your help. And you helped a lot already, so a big thanks to you :)

chronos

  • Jr. Member
  • **
  • Posts: 70
    • PascalClassLibrary
Re: Handling exceptions in Lazarus applications
« Reply #9 on: September 06, 2010, 10:19:41 am »
Another topic is logging exceptions in threads. I have done some investigation and written some info http://wiki.freepascal.org/Logging_exceptions#Handling_thread_exceptions

Info about map files are empty yet. http://wiki.lazarus.freepascal.org/Logging_exceptions#Using_map_file

It would be good to make some advanced logging component as http://www.eurekalog.com/screenshots_delphi.php

I have started to create one but there are many problems around. For example get list of running threads and call stack of all of them. We have just GetProcessID and GetThreadID functions.
Another missing info in call stack is module name as is visible in http://www.eurekalog.com/screenshot.php?src=docs/hlp_gui_dlg2.gif



mmab

  • Jr. Member
  • **
  • Posts: 65
Re: Handling exceptions in Lazarus applications
« Reply #10 on: November 20, 2010, 02:53:22 pm »
I've noticed one thing :
If you select the display numbers option at the compiler options, and use upx after exe created, the exe size becomes small and
it doesn't show line numbers but addresses are the same as uncompressed exe's which could be useful.



 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads