Delphi XE2 Update 2 , 64 bit and Datasnap

I have only encountered this problem today, but as I have had a long line of issues to work around so far with 64 bit XE2 I wanted to ask the question upfront before I start dive in again with more indepth investigations…

Have you found there to be any generic access violation problems with 64 bit XE2 ROSDK and Datasnap ? Our position is this :-

64 bit RO server with TROSuperTCPServer
32 bit client connecting via TROSuperTCPChannel

The client (still 32 bit due to some 3rd party libraries at present) makes calls through a TRODataSnapConnection (select, insert, update , execute etc). Latest ROSDK is in use, also using Delphi XE2 Update 2 and latest SDAC for backend connectivity to SQL server.

The code runs fine in 32 bit in D2007 and continues to do so in XE2 update 2 32 bit. Retrieval of data through ClientDataset appears to pose no problems with a 64bit server, yet updating data in one form or another invariably causes access violations very quickly. When I say very quickly, it appears that issuing statements in quick succession brings on the AV. This does not appear related to any one SQL statement, I have triggered it in a number of places now. I have attached a screenshot of a typical exception.

My next steps are to try and replicate this in a sample client / server project I can share, but if you have any pointers in the meantime, I’d be most grateful…

Paul.

it is strange.
I’ve tested our Datasnap sample : x64 server and x32 client and no problems were detected: it works as expected.
In case you don’t use IROObjectRetainer interface, TROObjectDisposer should just free added objects.

Hi Evgeny,

Sorry it’s taken me a while to get back to this, it is our top priority for getting a XE2 / 64 bit version released, but as usual day to day things interrupt.

I’ve now been investigating further (after installing the latest ROSDK – 6.0.55.957) and I can now at least duplicate the problem at will in our software. I have not yet produced a simple test case that I can share, but here is some further information that I hope will help you point me in the right direction.

The attached screenshot now shows exactly where the problem is occurring, namely in uRoServer. TROInvoker.CustomHandleMessage, specifically the “mtd” call. As I’ve said, this is intermittent, but I can now get it to readily repeat by having two clients perform a long string of datasnap “execute” tasks simultaneously. I had thought the problem may be specific to 64 bit, but with this new test scenario, it is visible in 32 bit as well.

Of course it is at least reasonably likely that the problem is in my code, and I have attached a couple of pieces of source code that I feel may be at fault. The first is unRoPerClientClassFactory, which is my reworking or the PerClientClassFactory. Since I did this (around 2007), I know some of this functionality has been incorporated into the standard codebase and I need to look to see if I can remove my code as part of the investigation. I have also attached a sample _IMPL for a datamodule. It is not the one in question that has the problem – it does not do datasnap processing. However, I have included it because it is far shorter and it shows the general method I use for instantiating the data module. You will see the initialize procedure at the bottom which is called from the main form of the server. I do this in order to be able to specify a stored system parameter (AValue) which is a timeout value. You’ll see that I therefore do not create the class factory in the initialization, nor do I destroy it in the finalization. If it was in the initialization, how could I set a timeout that depended on a value being retrieved from a database ?

The only other area I have for investigation is something that I know is bad practice, but it is the result of a 10 year old code base… In order to execute a series of linked insert / delete / update statements we have in place a pseudo transactional model. That is, there are methods on the server to enable “StartTransaction”, “Commit” and “Rollback” functions. So if the client has a sequence that needs to all work or all fail, they are wrapped in calls to these methods. Although far from the ideal of a stateless server, it actually has been working well. I have done some investigation along the lines of removing the calls to these methods to see the impact, but it did not seem to make a difference.

In your earlier answer to me you mentioned IROObjectRetainer and TROObjectDisposer. I think I have seen these in a sample application, but I’m honestly not sure of their function or when to use them correctly.

If there are any avenues you can suggest to me at this stage, I would be most grateful as this is stopping us dead in our tracks with regards releasing the next version of our software.

Paul.

Hi Evgeny,

I have continued looking at the problem today and I’m in a position to give you a sample project demonstrating the problem. The attached sample is a cut down and reworked version of the RO datasnap client / server. In order to run it, you’ll just need to modify the ADO connection string in the server. It also needs a couple of tables creating in tempdb (or wherever you choose). Basically two tables called “DataTable1” and “DataTable2”, both with these two fields - “Code” int and “Value” nvarchar(50). The fields it uses are irrelevant, but as you can see, each “DataTable” relates to a button on the client. All those buttons do is clear their respective target tables and populate with 5000 records. If you run both of those together, you should get the error I’ve been experiencing. That is, open the server and two copies of the client, pressing the DataTable1 button on client A and the DataTable2 button on client B. And just to confirm, the test environment is DXE2 Update 2 with ROSDK 6.0.55.957

As a further check, I have also used the same project in D2007 with ROSKDK 6.0.45.821, which is our current live development environment. I do NOT see the problem there, i.e. the test project continuously works without a problem. A further check I will do is to use the latest ROSDK back in D2007 to hopefully nail down that the issue should be in RO and not DXE2.

I’d be extremely grateful if you could take a look at this as soon as you can.

Thanks,

Paul.

thanks for testcase.
it was fixed as 52123.
workaround: pls update uRODataSnapBaseAppServer.pas :
procedure TRODataSnapBaseAppServer.AS_Execute(const ProviderName: UnicodeString; const CommandText: UnicodeString; var Params: Binary; var OwnerData: AnsiString);
var lProvider:TCustomProvider;
lParams,lOwnerData:OleVariant;
begin

lProvider := GetProviderByName(ProviderName);
lOwnerData := OwnerData;
lParams := VariantFromBinary(Params);
lProvider.Execute(Commandtext,lParams,lOwnerData);
// FreeAndNil(Params); //<<<<< comment this line
Params := BinaryFromVariant(lParams);
OwnerData := VarToAnsiStr(lOwnerData);
end;

Thanks Evgeny, That has worked, quite an anticlamax to find out it was a simple one line fix after all the time spent trying to hunt down a common cause for the problems it caused!

Whilst I’m in the area, could you comment on my method of creating the class factories ? In the demo projects, I invariably see TROClassFactory.Create in the initialization section and an UnregisterClassFactory in the finalization. However, in order to pass a variable timout parameter to the TROPerClientCalssFactory, I move the creation of the class factory into a separate procedure which gets called from the main server code. Is this a valid approach ? Also, what is the benefit or purpose of the UnregisterClassFactory - sometimes I see it in the demos, sometimes not.

Thanks,

Paul.

in general, using of this code is enough:
initialization
fROPerClientClassFactory := TROPerClientClassFactory.Create(‘IAppServer1’, Create_DataSnapModule, TAppServer_Invoker,15*60);

finalization
UnregisterClassFactory(fROPerClientClassFactory);
end.
but your solution is also valid.
UnregisterClassFactory was put into _impl for avoiding deadlocks in dll