delphi - DBXPool Corrupts Memory on Failure to Connect -
when dbxpool
used delegateconnection
on tsqlconnection
, if sqlserver unavailable when call tsqlconnection.open
method, timeout first time. if subsequently call open
again, misbehave. in production service, kills process without warning -- no exceptions raised, nothing. process disappears... in simple app created test dbxpool
, thinks tsqlconnection
connected, when not.
has had troubles dbxpool
delegateconnection
can offer suggestions?
thanks!
<<< 7/23 edit #2 >>>
i used code in edit #1 below trace through dbx framework. following method called when dbxpool used:
(unit dbxdelegate)
procedure tdbxdelegateconnection.open; begin if not fconnection.isopen begin tdbxaccessorconnection(fconnection).open; end; end;
... calls following method, called whether or not dbxpool used:
(unit dbxcommon)
procedure tdbxconnection.open; begin // mark state open memory can deallocated // if derived open or meta query fail fopen := true; derivedopen; databasemetadata; end;
notice comment. when exception occurs (e.g., wrong username or timeout, etc.), following code called when dbxpool not used.
(unit dbxcommon)
procedure tdbxconnection.close; begin closeallcommands; rollbackalltransactions; derivedclose; settraceinfoevent(nil); freeandnil(fdatabasemetadata); fopen := false; end;
because fopen
doesn't set false
when dbxpool used, causes code execute shouldn't next time derivedopen
called, results in accessviolation , memory corruption. rtl catches it, doesn't (e.g., production service killed windows). haven't been able trace deeper yet dbxdelegate determine why doesn't catch exception , call tdbxconnection.close
.
<<< 7/23 edit #1 >>>
per ken's suggestion, attaching simple example app. service app dies. app showing access violation in dbxmss.dll (today). yesterday didn't raise exception on second click, returned 'connected' true. seems memory corruption me...
build , run app on machine or w/o sqlserver. click each button few times. both return error on first click. 'with dbxpool' think it's connected beginning second click. if lucky, might see av. 'w/o dbxpool' button fail every time, correct.
project1.dpr
program project1; uses forms, unit1 in 'unit1.pas' {form1}; {$r *.res} begin application.initialize; application.mainformontaskbar := true; application.createform(tform1, form1); application.run; end.
unit1.dfm
object form1: tform1 left = 0 top = 0 caption = 'form1' clientheight = 301 clientwidth = 562 color = clbtnface font.charset = default_charset font.color = clwindowtext font.height = -11 font.name = 'tahoma' font.style = [] oldcreateorder = false oncreate = formcreate pixelsperinch = 96 textheight = 13 object button1: tbutton left = 40 top = 8 width = 75 height = 25 caption = 'with dbxpool' taborder = 0 onclick = button1click end object button2: tbutton left = 40 top = 39 width = 75 height = 25 caption = 'w/o dbxpool' taborder = 1 onclick = button2click end object sqlconnection1: tsqlconnection drivername = 'mssql' getdriverfunc = 'getsqldrivermssql' libraryname = 'dbxmss.dll' loginprompt = false params.strings = ( 'driverunit=dbxmssql' 'driverpackageloader=tdbxdynalinkdriverloader,dbxcommondriver150.' + 'bpl' 'driverassemblyloader=borland.data.tdbxdynalinkdriverloader,borla' + 'nd.data.dbxcommondriver,version=15.0.0.0,culture=neutral,publick' + 'eytoken=91d62ebb5b0d1b1b' 'metadatapackageloader=tdbxmssqlmetadatacommandfactory,dbxmssqldr' + 'iver150.bpl' 'metadataassemblyloader=borland.data.tdbxmssqlmetadatacommandfact' + 'ory,borland.data.dbxmssqldriver,version=15.0.0.0,culture=neutral' + ',publickeytoken=91d62ebb5b0d1b1b' 'getdriverfunc=getsqldrivermssql' 'libraryname=dbxmss.dll' 'vendorlib=sqlncli10.dll' 'maxblobsize=-1' 'osauthentication=false' 'preparesql=true' 'errorresourcefile=' 'drivername=mssql' 'schemaoverride=%.dbo' 'hostname=127.0.0.1' 'database=database' 'user_name=username' 'password=password' 'blobsize=-1' 'localecode=0000' 'isolationlevel=readcommitted' 'os authentication=false' 'prepare sql=false' 'delegateconnection=dbxpool' 'dbxpool.maxconnections=20' 'dbxpool.minconnections=1' 'dbxpool.connecttimeout=1000' 'dbxpool.driverunit=dbxpool' 'dbxpool.delegatedriver=true' 'dbxpool.dbxpool.maxconnections=20' 'dbxpool.dbxpool.minconnections=1' 'dbxpool.dbxpool.connecttimeout=1000' 'dbxpool.dbxpool.driverunit=dbxpool' 'dbxpool.dbxpool.delegatedriver=true' 'dbxpool.dbxpool.drivername=dbxpool' 'dbxpool.drivername=dbxpool') vendorlib = 'sqlncli10.dll' left = 8 top = 8 end object sqlconnection2: tsqlconnection drivername = 'mssql' getdriverfunc = 'getsqldrivermssql' libraryname = 'dbxmss.dll' loginprompt = false params.strings = ( 'driverunit=dbxmssql' 'driverpackageloader=tdbxdynalinkdriverloader,dbxcommondriver150.' + 'bpl' 'driverassemblyloader=borland.data.tdbxdynalinkdriverloader,borla' + 'nd.data.dbxcommondriver,version=15.0.0.0,culture=neutral,publick' + 'eytoken=91d62ebb5b0d1b1b' 'metadatapackageloader=tdbxmssqlmetadatacommandfactory,dbxmssqldr' + 'iver150.bpl' 'metadataassemblyloader=borland.data.tdbxmssqlmetadatacommandfact' + 'ory,borland.data.dbxmssqldriver,version=15.0.0.0,culture=neutral' + ',publickeytoken=91d62ebb5b0d1b1b' 'getdriverfunc=getsqldrivermssql' 'libraryname=dbxmss.dll' 'vendorlib=sqlncli10.dll' 'maxblobsize=-1' 'osauthentication=false' 'preparesql=true' 'errorresourcefile=' 'drivername=mssql' 'schemaoverride=%.dbo' 'hostname=127.0.0.1' 'database=database' 'user_name=username' 'password=password' 'blobsize=-1' 'localecode=0000' 'isolationlevel=readcommitted' 'os authentication=false' 'prepare sql=false') vendorlib = 'sqlncli10.dll' left = 8 top = 39 end end
unit1.pas
unit unit1; interface uses windows, messages, sysutils, variants, classes, graphics, controls, forms, dialogs, dbxmssql, stdctrls, db, sqlexpr, dbxpool; type tform1 = class(tform) button1: tbutton; sqlconnection1: tsqlconnection; sqlconnection2: tsqlconnection; button2: tbutton; procedure button1click(sender: tobject); procedure formcreate(sender: tobject); procedure button2click(sender: tobject); private { private declarations } public { public declarations } end; var form1: tform1; implementation uses dbxcommon; {$r *.dfm} procedure tform1.button1click(sender: tobject); begin sqlconnection1.close; sqlconnection1.open; if sqlconnection1.connected messagedlg('connected connection 1', mtinformation, [mbok], 0); end; procedure tform1.button2click(sender: tobject); begin sqlconnection2.close; sqlconnection2.open; if sqlconnection2.connected messagedlg('connected connection 2', mtinformation, [mbok], 0); end; procedure tform1.formcreate(sender: tobject); begin // testing purposes, shorten timeout timeout occurs sqlconnection1.params.values[tdbxpropertynames.connecttimeout] := '1'; sqlconnection2.params.values[tdbxpropertynames.connecttimeout] := '1'; end; end.
embarcadero support notified me today issue has been fixed , available in next general release (e.g., xe2).
Comments
Post a Comment