#1 2022-08-25 19:44:00

Wanderlan
Member
From: Brazil
Registered: 2022-08-25
Posts: 4

Fatal Error (Exception External:?) in Interfaced based Services

Scenario:
Windows 10, 64 bit Lazarus 2.2.2, 64 bit Freepascal 3.2.2
Sample 14 - Interfaced based services

In Project14ServerHttp.dpr
Change the method 'Add' by inserting an exception:
function TServiceCalculator.Add(n1, n2: integer): integer;
begin
result := n1+n2;
raise Exception.Create('Test'); // <<< insert this exception
end;

In browser type:
http://localhost:8888/root/calculator/add?n1=1&n2=2
The first execution is ok, the exception is showed correctly
but execute again... the server goes down with the message... >>> Fatal error, External Exception: ?

I tracked the bug, it seems occurs in the CallMethod assembly code (starting at line 57968 in mormot.pas)

Last edited by Wanderlan (2022-08-25 19:47:32)

Offline

#2 2022-08-26 06:27:21

sakura
Member
From: Germany
Registered: 2018-02-21
Posts: 218
Website

Re: Fatal Error (Exception External:?) in Interfaced based Services

Service Methods shall never leak Exceptions, rather work with return codes. IIRC that is mentioned in the documentation. Thus allowing the framework to optimize for speed. If exceptions may occur in your service method, you are required to use try...except...end to catch those.

Offline

#3 2022-08-26 16:41:32

Wanderlan
Member
From: Brazil
Registered: 2022-08-25
Posts: 4

Re: Fatal Error (Exception External:?) in Interfaced based Services

Anyway, it's a bug in the framework and I would like it fixed.
I find it in the documentation about leaked exceptions, but as mere recommendation.

16.8.1. Error handling

This is why exceptions should better be intercepted on the server side, with a try .. except block within the service methods, then converted into low level DTO types, specific to the service, then explicitly transmitted as error codes to the client.

The first rule is that raising exception should be exceptional - as its name states: exceptional. I mean, service code should not raise an exception in normal execution, even in case of wrong input

But I found these snippets presenting launching exception from user services as *FRAMEWORK FEATURE*:

14.9. Handling errors

When using Ctxt.Input*[] properties, any missing parameter will raise an EParsingException. ***It will therefore be intercepted by the server process (as any other exception), and returned to the client with an error message containing the Exception class name and its associated message***.
::::
***Note that the framework core will catch any exception during the method execution, and will return a "Internal Server Error" / HTTP_SERVERERROR = 500 error code with the associated textual exception details.***

16.6.4. Enhanced sample: remote SQL access
::::
procedure TServiceRemoteSQL.Connect(aEngine: TRemoteSQLEngine;
::::
begin
  if fProps<>nil then
    raise Exception.Create('Connect called more than once'); <<<<< one of many "unOfficial" leaked exceptions showed in documentation wink
  fProps := TYPES[aEngine].Create(aServerName,aDatabaseName,aUserID,aPassWord);
end;
::::
***Any exception during SynDB.pas process, ***or raised manually*** in case of wrong use case will be transmitted to the client, just as expected.***

16.8.1. Error handling

Usually, in Delphi applications (like in most high-level languages), errors are handled via exceptions. By default, any Exception raised on the server side, within an interface-based service method, will be intercepted, and transmitted as an HTTP error to the client side, then a safe but somewhat obfuscated EInterfaceFactoryException will be raised, containing additional information serialized as JSON.

25.2.4. Exception handling

Of course, this logging mechanism is able to intercept the raise of exceptions, ***including the worse (e.g. EAccessViolation), to be logged automatically in the log file***, as such:

---------------------
I suspect that this error does not occur in 32 bit. I will test and post the results here as soon as I have time.
Anyway your workaround is acceptable and is the pattern used in languages that do not have exception handling such as "ANSI C", Oberon and "Go".

Thank you for your quick response
PS: Sorry I'm such a boring and nosy guy...

Last edited by Wanderlan (2022-08-26 17:44:34)

Offline

#4 2022-08-27 07:48:55

danielkuettner
Member
From: Germany
Registered: 2014-08-06
Posts: 330

Re: Fatal Error (Exception External:?) in Interfaced based Services

@sakura You should think about an unwanted exception in your sm and the manual inserted raise as an example for that.
Than it's interesting because I often see such external exceptions in my log files and misinterpreted these.

Offline

Board footer

Powered by FluxBB