Zeos 7.3-200a1058, Oracle ungraceful disconnect leaks a TZOracleTransaction object
Posted: 05.10.2020, 13:26
Hello,
The case is easy to reproduce. Have a TZConnection connected to an Oracle host, while having .AutoCommit on false. Now, unplug your network cable (or disconnect from VPN, just make sure there is no connection between the client and the server anymore) and call ZConnection.Disconnect.
It will fail as there is no connection anymore, which is fine. The problem is, it is leaking a TZOracleTransaction object, created in ZDbcOracle.pas, TZOracleConnection.Open, line 595:
During the Disconnect call, this is attempted to be freed in ZDbcOracle.pas, TZOracleConnection.InternalClose, line 831:
As this is an interface, assigning nil on it attempts to destroy the object. TZOracleTransaction.BeforeDestruction calls .Rollback:
And, HandleErrorOrWarning is throwing an exception (during the destruction of TZOracleTransaction), effectively leaving the transaction object alive.
I might be wrong, so I'll not create a patch, but my idea would be to check for destruction before throwing an exception or include a new parameter for
HandleErrorOrWarning to force it NOT to raise an exception.
The case is easy to reproduce. Have a TZConnection connected to an Oracle host, while having .AutoCommit on false. Now, unplug your network cable (or disconnect from VPN, just make sure there is no connection between the client and the server anymore) and call ZConnection.Disconnect.
It will fail as there is no connection anymore, which is fine. The problem is, it is leaking a TZOracleTransaction object, created in ZDbcOracle.pas, TZOracleConnection.Open, line 595:
Code: Select all
fLocalTransaction := TZOracleTransaction.CreateLocal(Self);
Code: Select all
fLocalTransaction := nil;
Code: Select all
Status := FOwner.FPlainDriver.OCITransRollback(FOwner.FContextHandle,
FOwner.FErrorHandle, OCI_DEFAULT);
if Status <> OCI_SUCCESS then
FOwner.HandleErrorOrWarning(FOwner.FErrorHandle, Status, lcTransaction, 'TRANSACTION ROLLBACK', Self);
I might be wrong, so I'll not create a patch, but my idea would be to check for destruction before throwing an exception or include a new parameter for
HandleErrorOrWarning to force it NOT to raise an exception.