Subject AV when switching to another app
Author Toby Leonard
I've been having some issues with profiling (using AQtime) an app that uses
the Unified Interbase components, and figured I'd give IBO a try. The test
system is XPSP2, D2005 Update 1, IBO Eval 4.5, and FB embedded 1.5.2.4731.

I can run the code below in the IDE or standalone, and as long as I leave it
focused until I close it, it performs as expected. However if I switch to
another app while the main processing is going on or after I've stopped it,
the app AVs at 00000000 trying to read 00000000. Under AQtime I get the AV
regardless.

Testing this, it looks like I can have as little as the TIB_Session created in
the thread, and the AV occurs.

(Yeah I know some of the stuff in here is bad coding practice, like the A.PM
and Sleep(1) combo. I wouldn't normally do such things - this is just a
throwaway test app.)

Any help would be greatly appreciated. Thanks!

unit Unit22;

interface

uses
Forms, Controls, StdCtrls, Classes, ExtCtrls;

type
TForm22 = class(TForm)
Panel1: TPanel;
Button1: TButton;
LB: TListBox;
procedure Button1Click(Sender: TObject);
end;

var
Form22: TForm22;

implementation

{$R *.dfm}

uses
Windows, SysUtils, IB_Components, SyncObjs;

const
MAX_THREADS = 10;

type
TIBTestThread = class(TThread)
private
FDBSession: TIB_Session;
FDBConnection: TIB_Connection;
FDBTransaction: TIB_Transaction;
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
end;

var
KeepGoing: Boolean;
TotalThreads: Cardinal;
CS: TCriticalSection;

constructor TIBTestThread.Create;
begin
inherited Create(False);

FreeOnTerminate := True;

FDBSession := TIB_Session.Create(nil);
FDBConnection := TIB_Connection.Create(FDBSession);
FDBConnection.IB_Session := FDBSession;
FDBConnection.Path := ExtractFilePath(ParamStr(0)) + 'foo.fdb';
FDBConnection.Username := 'foo';
FDBConnection.Password := 'bar';
FDBConnection.Connect;
FDBTransaction := TIB_Transaction.Create(FDBSession);
FDBTransaction.IB_Connection := FDBConnection;
end;

destructor TIBTestThread.Destroy;
begin
CS.Enter;
try
Dec(TotalThreads);
finally
CS.Leave;
end;

FDBTransaction.Free;
FDBConnection.Disconnect;
FDBConnection.Free;
FDBSession.Free;

inherited;
end;

procedure TIBTestThread.Execute;
var
Cursor: TIB_Cursor;
begin
Cursor := TIB_Cursor.Create(FDBSession);
try
Cursor.IB_Transaction := FDBTransaction;

Cursor.SQL.Text :=
'select ' +
' RDB$RELATION_NAME ' +
'from ' +
' RDB$RELATIONS';
Cursor.Open;
try
while not Cursor.Eof do
begin
Cursor.Next;
end;
finally
Cursor.Close;
end;
finally
Cursor.Free;
end;

Terminate;
end;

procedure TForm22.Button1Click(Sender: TObject);
var
StillThreads: Boolean;
begin
try
if Button1.Caption <> 'Go' then
begin
KeepGoing := False;
Exit;
end;

Button1.Caption := 'Stop';
try
CS := TCriticalSection.Create;
try
Button1.Enabled := False;
try
TotalThreads := 0;
KeepGoing := True;
finally
Button1.Enabled := True;
end;

while KeepGoing do
begin
CS.Enter;
try
if TotalThreads < MAX_THREADS then
begin
TIBTestThread.Create;
Inc(TotalThreads);
end;
finally
CS.Leave;
end;

Application.ProcessMessages;
Sleep(1);
end;

Button1.Enabled := False;
try
repeat
CS.Enter;
try
StillThreads := TotalThreads > 0;
finally
CS.Leave;
end;

Application.ProcessMessages;
Sleep(1);
until not StillThreads;
finally
Button1.Enabled := True;
end;
finally
CS.Free;
end;
finally
Button1.Caption := 'Go';
end;
except
on E:Exception do
begin
OutputDebugString(PChar('EXCEPTION - ' + E.ClassType.ClassName + ' - ' +
E.Message));
end;
end;
end;

end.

--
Toby