Root > Advanced topics > Using EurekaLog in DLL > What is the proper way to handle exceptions in DLL > Creating bug reports for DLL exceptions

Creating bug reports for DLL exceptions

Previous pageReturn to chapter overviewNext page   

 

Important: as a general rule, you should write your application in a such way that it will behave correctly without EurekaLog on board. This means that if your or 3rd party code throws an exception in a DLL - it must be handled in a way that you expect. For example, by showing an error message, canceling action, retrying, etc. Once your application behaves like it is supposed to do - then you add EurekaLog for it. EurekaLog will auto-handle all unhandled exceptions automatically (by hooking few well-known places), and for everything else - you can call EurekaLog from your own handlers when needed. In other words:

Incorrect: your application does not show messages for exceptions (or do other things you want) from DLL and you are adding EurekaLog in hopes to fix this behavior;
Correct: your application correctly handles DLL exceptions and you are adding EurekaLog to receive reports about such exceptions.

 

Exceptions should never leave DLLs. This means that exceptions should be handled in exported functions and converted to some error sign (a flag, an integer error code, HRESULT code, etc.). The entire life-time of any exception from DLL can be illustrated by this example:

 

 

Exception's life-time in COM applications

Also applicable to similar API styles

 

This example uses COM application for illustration, but the similar is true for any other good designed DLL with minor adjustments.

 

Notice that such approach will not create bug reports for the exceptions. Each exception from DLL (callee) is converted to "error code". No error message is shown to user. Error message shown to user comes from second exception - the one that was raised by caller/host.

 

Creating bug reports for DLL exceptions is not an easy question - because final handling of the exception is not under your control. It is the caller of your DLL who decides what to do with the exceptions from your DLLs. Surely, exception from your DLL may be handled as usual: by showing error message to end user, asking to send bug report to developers, etc. However, exception from your DLL may also be silently handled by the caller and failed action will be repeated. Or the caller may try to execute fallback method with alternative solution (for example, the code that tries to set application for auto-launch may write to HKEY_LOCAL_MACHINE registry key. If this action will fail due to application being run under limited user account - the code may switch to HKEY_CURRENT_USER key, e.g. re-try action with other params).

 

For these reasons you can not simply show error dialog and ask to send bug report - because:

If exception from your DLL will be handled as error by the caller - then the error message will appear twice: first from your DLL as bug report, second - from the caller;
If exception from your DLL will be handled as non-error by the caller (i.e. the caller may re-try action or try alternative solutions) - then your DLL will show "false" error message (user will see error dialog - even though requested action will be completed by the caller).

 

You can try to use different approaches for creating bug reports for exceptions in DLLs. A very simple approach would be to append call stack to exception message:

 

uses
  ComObj; // for HandleSafeCallException
 
function ConvertExceptionToHRESULT(E: Exception): HRESULT;
const 
begin
  Result := HandleSafeCallException(E + E.StackTrace, ExceptAddr, GUID_NULL, GUID_NULL, '');
end;

 

(Works for both "Lightweight DLL" and "Standalone DLL" profiles.)

 

This is a very simple, but still a good way. A great advantage is that this approach will work in any host - even if host have no exception tracer enabled. If exception from your DLL will be recognized as an error by the caller, then the caller will show error message - and your error message includes call stack. This will give you information about the problem. And this will work for any host - including Internet Explorer (ActiveX), Microsoft Office (COM plugins), etc.

 

However, the limitation of the above method is that it will not provide you a full bug report (with environment information, CPU/Assembly dump, etc.). It will only show a call stack.

 

Other possible solution would be to configure DLL to create bug report files silently - i.e. without dialogs and sending reports and to create new bug report for each exception that leaves DLL:

 

uses
  ComObj, // for HandleSafeCallException

  EBase;  // for HandleException
 
function ConvertExceptionToHRESULT(E: Exception): HRESULT;
begin
  HandleException(E);
  Result := HandleSafeCallException(E, ExceptAddr, GUID_NULL, GUID_NULL, '');
end;

 

(Works for both "Lightweight DLL" and "Standalone DLL" profiles.)

 

Therefore, all bug reports from DLL will be collected in bug reports output folder for DLL:

If your .exe host is not EurekaLog-enabled - you can't automatically show and/or send DLL bug reports. However, you may manually open bug reports to study bugs.
If your .exe host is EurekaLog-enabled - it can attach these files to its own bug report as additional files:
o[Recommended] If your application uses a single instance of exception tracer (i.e. host .exe has EurekaLog, DLL does not have EurekaLog - all DLLs are compiled with "Lightweight DLL" profile). This means that both host and DLLs will use the same exception tracer and the same options. Thus, all bug reports will be stored in the same file. You need to allow multiple bug reports in bug report file by setting "Max. reports in one file" option to value greater than 1. You should also set "Send entire bug report file with multiple reports" option to send all reports together.
o[Not recommended] If your application uses multiple instances of exception tracer (i.e. both host .exe and DLLs have EurekaLog - all DLLs are compiled with "Standalone DLL" profile). You can supply a name to bug report file as "help file name":

 
function ConvertExceptionToHRESULT(E: Exception): HRESULT;
begin
  HandleException(E);
  Result := HandleSafeCallException(E, ExceptAddr, GUID_NULL, GUID_NULL, 

    ExceptionManager.Info(E, ExceptAddr).Options.OutputLogFile(''));
end;

 

A caller may use help file name property to figure out file name with bug report from DLL. This report can be shown to user, or attached as additional file to bug report for second exception in caller module.

 

You can design and implement any other solution to create bug report files. You can combine the above solutions.

 

 

See also:




Send feedback... Build date: 2024-09-30
Last edited: 2024-07-08
PRIVACY STATEMENT
The documentation team uses the feedback submitted to improve the EurekaLog documentation. We do not use your e-mail address for any other purpose. We will remove your e-mail address from our system after the issue you are reporting has been resolved. While we are working to resolve this issue, we may send you an e-mail message to request more information about your feedback. After the issues have been addressed, we may send you an email message to let you know that your feedback has been addressed.


Permanent link to this article: https://www.eurekalog.com/help/eurekalog/dll_bug_reports.php