Jump to content
Wagner Landgraf

Is it possible that an exception does not inherits from Exception class?

Recommended Posts

Considering the following code:

try
except
  on E: Exception do
  begin
    DoSomething; 
    raise;
  end;
end;

Is it possible, in "real" applications (*), that in the case of something bad happens, DoSomething method does not execute?

 

(*) I know that any object can be raised as an exception, so I understand that in theory, you can have exception objects that do not inherit from Exception class.

 

But my question is more in this way: I know that my code doesn't raise any exception object that does not inherit from Exception. Also consider that third party libraries used do not do that.

Is it still possible that DoSomething method doesn't execute? Say, for example, if some really low level error happen, Windows API calls, DLLs, etc.?

Share this post


Link to post

Probably if the process is aborted, DoSomething will not execute. Same if power turned off. Same if fatal system error.

Share this post


Link to post
9 minutes ago, FPiette said:

Probably if the process is aborted, DoSomething will not execute. Same if power turned off. Same if fatal system error.

Assuming this is not sarcasm, as English is not my main language: my question refers to a situation where the application continues executing.

Share this post


Link to post

I am reluctant to write the trivial case, but it won't execute if just no exception bubbles up to that point, perhaps because it is caught (not necessary handled properly) at some deeper level.

 

Just curious: What problem are you actually trying to solve?

  • Like 1

Share this post


Link to post
6 minutes ago, Uwe Raabe said:

Just curious: What problem are you actually trying to solve?

I've detected an odd behavior in an application that I can't explain yet why it happened. I searched for database transaction management as I felt it was related to it. All the transaction-related code has the usually pattern try..except, having a Rollback in the except block followed by a raise.

 

Then I found there was only a single try..except which was constructed the way in my first post. DoSomething would be the rollback. All the other transaction-handling in the application code had the rollback just directly in the except block, not inside the "on E: Exception do". Interestingly enough, the different try..except was in a place that is somehow involved with the error.

 

So I wondered if there might be a remote chance that some error happened, a non Exception object was raised, the rollback was not called, the exception was re-raised and everything continued as usual, but without the call to the rollback.

Edited by Wagner Landgraf

Share this post


Link to post

maybe this can happens because the many languages use a "CLR" as proxy (between original language and platform target) then, I think that can happens in rare case...

Quote

The C# language's exception handling features help you deal with any unexpected or exceptional situations that occur when a program is running. Exception handling uses the try, catch, and finally keywords to try actions that may not succeed, to handle failures when you decide that it's reasonable to do so, and to clean up resources afterward. Exceptions can be generated by the common language runtime (CLR), by .NET or third-party libraries, or by application code. Exceptions are created by using the throw keyword.

https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/exceptions/

Quote

20.3 The System.Exception class

The System.Exception class is the base type of all exceptions. This class has a few notable properties that all exceptions share:

Message is a read-only property of type string that contains a human-readable description of the reason for the exception.

InnerException is a read-only property of type Exception. If its value is non-null, it refers to the exception that caused the current exception. (That is, the current exception was raised in a catch block handling the InnerException.) Otherwise, its value is null, indicating that this exception was not caused by another exception. The number of exception objects chained together in this manner can be arbitrary.

 

The value of these properties can be specified in calls to the instance constructor for System.Exception.

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/exceptions

Edited by programmerdelphi2k
  • Like 1

Share this post


Link to post

You could try to write the except statement with the else syntax to see if it gets caught.  I had to do this in web core, null items will raise an exception that are a special exception.

 

  try
...
  except
    on E: Exception do
      Logger.Warn('Failed app tool init : ' + E.Message, self);
    else // handle everything else
      Logger.Warn('Failed app tool init', self);
  end;

 

  • Like 4

Share this post


Link to post
16 hours ago, Wagner Landgraf said:

Then I found there was only a single try..except which was constructed the way in my first post. DoSomething would be the rollback. All the other transaction-handling in the application code had the rollback just directly in the except block, not inside the "on E: Exception do". Interestingly enough, the different try..except was in a place that is somehow involved with the error.

 

So I wondered if there might be a remote chance that some error happened, a non Exception object was raised, the rollback was not called, the exception was re-raised and everything continued as usual, but without the call to the rollback.

Its simple to check this by changing the code to handle all exceptions, not just ones that derive from Delphi's Exception class. 

 

I wonder, how would a language exception raised by another module in your process appear as when it reach your exception handler?

Edited by David Heffernan

Share this post


Link to post
16 hours ago, Wagner Landgraf said:

All the transaction-related code has the usually pattern try..except, having a Rollback in the except block followed by a raise.

I use this construct and this will go well with any exceptions but there is a weakness if the library will not set InTransaction how it should.

try
  StartTransaction;
  ....
  Commit;
finally
  if InTransaction then
    Rollback;
end;

 

Edited by Cristian Peța

Share this post


Link to post
2 hours ago, David Heffernan said:

I wonder, how would a language exception raised by another module in your process appear as when it reach your exception handler?

I believe this is what your asking for, something like this, focused on the else clause, adjusted for the faulting module. 

 

"You can access the current except value via JSExceptValue in unit JS."

"Note that this is only valid inside the catch-block. The compiler will not warn, if you use it outside. "

Unit MyModule;
Interface
Uses SysUtils, Math, JS;
Function DoIt(n: integer): double;
Implementation
Function DoIt(n: integer): double;
var E: Exception;
Begin
  try
    Result:=double(7.0)/n;
    if not IsFinite(Result) then
      if n=0 then
        raise EZeroDivide.Create
      else
        raise EOverflow.Create;
  except
    on EZeroDivide do Result:=0.0;
    on E2: EOverflow do Result:=0.0;
    else
      raise EAbort.Create('Something other: '+String(JS.JSExceptObject));
  end;
End;
End.

Reference : https://wiki.freepascal.org/Pas2js_Transpiler#Translating_try..except

 

Share this post


Link to post
3 hours ago, David Heffernan said:

Its simple to check this by changing the code to handle all exceptions, not just ones that derive from Delphi's Exception class. 

Sure, that is already done. I was just wondering if that was a possible thing to happen. But it looks like that's not the case.

Share this post


Link to post

as rule, the "order" help you when exception can occurs... but it's a paranoic way not?

type
  ENotRelated = exception;

procedure TForm1.Button1Click(Sender: TObject);
begin
  try
    raise ENotRelated.Create('help help');
  except
    on E: EDivByZero do // a specific exception
      ShowMessage('Ok, Im Specific');

    // on E:XXXX do ....

    on E: exception do               // a generic exception
      ShowMessage('Ok, Im Generic'); // by default, these line will be called...
    else                             // anyother not related...
      ShowMessage('Ok, Im ELSE');
  end;
end;

 

Edited by programmerdelphi2k

Share this post


Link to post
5 hours ago, Wagner Landgraf said:

Sure, that is already done. I was just wondering if that was a possible thing to happen. But it looks like that's not the case.

There is a case, though: if the code inside the try block calls something in a DLL and that DLL function does not trap any exceptions raised inside the DLL code these would bubble up the exception handler stack into your try except block, be trapped there but not recognized as deriving from the Exception class. This would even be the case if the DLL is written in Delphi, unless DLL and EXE are build with the same Delphi version and with run-time packages enabled for both projects.

  • Thanks 1

Share this post


Link to post
2 minutes ago, PeterBelow said:

There is a case, though: if the code inside the try block calls something in a DLL and that DLL function does not trap any exceptions raised inside the DLL code these would bubble up the exception handler stack into your try except block, be trapped there but not recognized as deriving from the Exception class. This would even be the case if the DLL is written in Delphi, unless DLL and EXE are build with the same Delphi version and with run-time packages enabled for both projects.

Thank you very much. That's the kind of situation I was wondering. So it's possible, especially because in the end Delphi apps are calling DLLs often. I just don't know the odds of such situation to happen. 

Share this post


Link to post
14 hours ago, David Heffernan said:

I wonder, how would a language exception raised by another module in your process appear as when it reach your exception handler?

Indeed

4 hours ago, PeterBelow said:

There is a case, though: if the code inside the try block calls something in a DLL and that DLL function does not trap any exceptions raised inside the DLL code these would bubble up the exception handler stack into your try except block, be trapped there but not recognized as deriving from the Exception class. This would even be the case if the DLL is written in Delphi, unless DLL and EXE are build with the same Delphi version and with run-time packages enabled for both projects.

 

Share this post


Link to post

Dont know if Mobile is relevant for your case too,  but I know that some systen exceptions may be untrapped. 

A solution was to extract try-except into separate method and implement a kindof double try-except to ensure to catch them all. 

Share this post


Link to post

Mobile is not the case here. But for all intents and purposes, it's clear, from the responses of some helpful gentlemen here, that "on E: Exception" is not a 100% safe approach.

Share this post


Link to post
13 hours ago, Wagner Landgraf said:

Mobile is not the case here. But for all intents and purposes, it's clear, from the responses of some helpful gentlemen here, that "on E: Exception" is not a 100% safe approach.

That is extremely significant.  I have countless numbers of these and I am starting to wonder if they should be rewritten to

try
  // ...
except
  on E: Exception 
    do begin
      
    end
  else raise;
end;      

and then have a general handler for those further out.

 

Or.... just log "An unidentified terrible event happened."

Share this post


Link to post
21 minutes ago, Lars Fosdal said:

I have countless numbers of these

Don't you just have a small number of top level exception handlers?

Share this post


Link to post
33 minutes ago, David Heffernan said:

Don't you just have a small number of top level exception handlers?

When dealing with live data, there is no end to what can go wrong - so no - I do not have a small number of top level exception handlers.

Share this post


Link to post
2 minutes ago, Lars Fosdal said:

When dealing with live data, there is no end to what can go wrong - so no - I do not have a small number of top level exception handlers.

Sounds like the worst of all worlds. The noise of try / except blocks everywhere, and old school checking for errors at all steps!

Share this post


Link to post

With TCP/UDP/Serial, JsonRPC, REST, Databases and conversions and partial data transfers possible - you tend to accumulate a number of these.

 

Share this post


Link to post
1 hour ago, Lars Fosdal said:

I have countless numbers of these and I am starting to wonder if they should be rewritten to

That is not needed. The else is implicit in the try..except block, if an exception is not trapped in the "on" clause, it's re-raised.

The point here is if you have code that needs to be executed, like a transaction rollback, or a log message that needs to be generated, etc.

  • Thanks 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×