You are not logged in.
Pages: 1
Hi AB,
yesterday i solved a BUG in our mORMot Service and I'm not sure if it's a Berlin 10.2 BUG(Feature) or something in your mormot.pas:CallMethod Assembler Code. As it is not easy to make a demo i try to explain my observations and may be you have an idea.
We have a SOAP Interface Function like this
IDFMyService = interface(IInvokable)
...
function GetDetails(const AIDs : TIntegerDynArray) : RDetailsResult;
the function GetDetails works like this in principle - We use this for a long time now
function <class>.GetDetails(const AIDs : TIntegerDynArray) : RDetailsResult;
var
LStmt : ISQLDBRows;
LConnection : TSQLDBConnectionProperties;
begin
FillChar(Result, SizeOf(Result), 0);
LConnection := CreateConnection;
if assigned(LConnection) then try
LStmt := LConnection.ExecuteInlined(<Any SQL>, True);
finally
FreeAndNil(LConnection);
end;
end;
Using this function from Client sometimes throws Exception in line mormot.pas 57405:
procedure CallMethod(var Args: TCallMethodArgs);
....
call [esi].TCallMethodArgs.method
// retrieve result
mov cl, [esi].TCallMethodArgs.resKind <- Exception
To eliminate the Exception i had to set LStmt to nil after using it and before function end;
function <class>.GetDetails(const AIDs : TIntegerDynArray) : RDetailsResult;
var
LStmt : ISQLDBRows;
LConnection : TSQLDBConnectionProperties;
begin
FillChar(Result, SizeOf(Result), 0);
LConnection := CreateConnection;
if assigned(LConnection) then try
LStmt := LConnection.ExecuteInlined(<Any SQL>, True);
try
... Do something with LStmt
finally
LStmt := nil;
end;
finally
FreeAndNil(LConnection);
end;
end;
I think there is something wrong with interface release stuff
what do you think
BR
Stefan
Last edited by itSDS (2017-08-01 10:49:11)
Rad Studio 12.1 Santorini
Offline
Here is more information concerning the Exception EAccessViolation:
:7786b802 KERNELBASE.RaiseException + 0x62
mORMot.CallMethod(???)
mORMot.TServiceMethodExecute.RawExecute($463F8A4,0)
mORMot.TServiceMethodExecute.ExecuteJson((...),']',$2F3F9D0,False)
mORMot.TServiceFactoryServer.ExecuteMethod($352D460)
mORMot.ComputeResult
mORMot.TSQLRestServerURIContext.InternalExecuteSOAByInterface
mORMot.TSQLRestRoutingREST.ExecuteSOAByInterface
mORMot.TSQLRestServerURIContext.ExecuteCommand
mORMot.TSQLRestServer.URI($463FBD0)
mORMotHttpServer.TSQLHttpServer.Request($34676A8)
SynCrtSock.THttpServerGeneric.Request($34676A8)
SynCrtSock.THttpApiServer.Execute
Rad Studio 12.1 Santorini
Offline
It's a Delphi feature, not a bug.
Compiler create code like this:
function GetDetails(const AIDs : TIntegerDynArray) : RDetailsResult;
var
LStmt : ISQLDBRows;
LConnection : TSQLDBConnectionProperties;
begin
Pointer(LStmt) := nil; // <- compiler create this code for you
try // <- compiler create this code for you
FillChar(Result, SizeOf(Result), 0);
LConnection := CreateConnection;
if assigned(LConnection) then try
LStmt := LConnection.ExecuteInlined(<Any SQL>, True);
finally
FreeAndNil(LConnection);
end;
finally // <- compiler create this code for you
_IntfClear(LStmt); // <- compiler create this code for you
end; // <- compiler create this code for you
end;
And, as you can see, database connection destroyed earlier than statement object. But statement object refers to database connection, and when statement object destructor called there is an access violation.
Offline
... and it is clearly documented as such.
It happens when you are mixing interfaces and regular classes: they do not have the same exact live time.
Please read again https://synopse.info/files/html/Synopse … #TITLE_178
Everything is already explained here.
In short: you need to explicitly release the ISQLDBRows instance, by setting it to nil, BEFORE freeing the owner's connection.
So there is no bug in the framework, only how you use it.
And don't create a connection properties before each database access.
It is VERY inefficient.
Of course, most of the time you will initialize your TSQLDBConnectionProperties globally for your process, then release it when it ends.
Offline
ty chaa and ab
you're right i have missed this part in your documentation.
I rewrote my code an allocate the Connection Properties at service Creation now.
Rad Studio 12.1 Santorini
Offline
Pages: 1