1

Topic: Handling exception in DLL

Respected , kind day.
Faced a problem:
The project: Delphi XE + FireBird.
I use in the program dynamic library which itself and I develop.
The code of a call of library:

var
DLLRoutine: function (AppHandle:HWND; HostDb: TIBDatabase): Boolean; stdcall;
DLLHandle: THandle;
...
DLLHandle: = LoadLibrary (PChar (lib));
try
@DLLRoutine: = GetProcAddress (DLLHandle, PChar (func));
if Assigned (DLLRoutine) then
DLLRoutine (Application. Handle, Base.ibCon)
else
MessageDlg (' Dynamic function ' + aRunStr + ' is not found ', mtInformation, [mbOK], 0);
finally
FreeLibrary (DLLHandle);
end;

The handling code at outswapping DLL:

procedure MainDllProc (Reason: integer);
var
i: integer;
begin
//At loading DLL
if (Reason = windows. DLL_PROCESS_ATTACH)
then
begin
Base: = TBase. Create (Application);
Res: = TRes. Create (Application);
dxInitializeGDIPlus;
end;
//At outswapping DLL
if (Reason = windows. DLL_PROCESS_DETACH)
then
begin
ReleaseExceptionObject;
dxFinalizeGDIPlus;
with Application do
begin
for i: = ComponentCount - 1 downto 0 do
try
if (Components [i] is TForm) then
Components [i].Free;
except
end;
for i: = ComponentCount - 1 downto 0 do
try
if (Components [i] is TDataModule) then
begin
Components [i].Free;
end;
except
end;
end;
end;
end;

Question essence:
If by call DLL in the output agent works exception which sends FireBird (handling of stored procedures and a call in procedure)

begin
exception xxx_xxx;
end

at end of operation with DLL the runtime program hangs up.
Noted one singularity of behavior of the program by an exception call:

Module Load: OLEACC.dll. No Debug Info. Base Address: $6CC30000. Process XXX.exe (7884)
Thread Start: Thread ID: 5796. Process XXX.exe (7884)

There is a separate flow which then at DLL_PROCESS_DETACH is not killed.
What to do in the present state of affairs?

2

Re: Handling exception in DLL

Forgot to add that if does not work exception DLL it is preempted without problems.

3

Re: Handling exception in DLL

Kirill Lagunov;
, starts/murders of flows and still it is a lot of that - the bad style, and sometimes also it is impossible to do in DLL_PROCESS_ATTACH/DLL_PROCESS_DETACH. About it it is written in MSDN, it would not be desirable to search again.
Make . Two exported from  functions Initialize/Finalize which cause at successful LoadLibrary. In all of them do.

4

Re: Handling exception in DLL

Kirill Lagunov;
Yes, forgot to add. To let out from dll  outside - too not so style smile

5

Re: Handling exception in DLL

YuRock;

Essence that that these  FB-shnye I do not create in DLL, they are processed on server side, and then sent to the program.

try
Base.itransStoredProc. Commit;
Result: = True;
except
on E: EIBError do
begin
Result: = False;
Base.itransStoredProc. Rollback;
end;
end;

And, as a matter of fact, I too do not create a flow in DLL.
Into account Initialize/Finalize out of DLL I esteem, but the question is a little in other smile

6

Re: Handling exception in DLL

Kirill Lagunov wrote:

the Essence that that these  FB-shnye I do not create in DLL

Kirill Lagunov wrote:

And, as a matter of fact, I too do not create a flow in DLL

You create. Units, which you use (for example which work with client library FB) is same "your program", as well as personally your code.  differences does not see.

7

Re: Handling exception in DLL

Kirill Lagunov wrote:

try
Base.itransStoredProc. Commit;
Result: = True;
except
on E: EIBError do
begin
Result: = False;
Base.itransStoredProc. Rollback;
end;
end;

This strange code only in any single instances can not lead to that the exception does not get "outside".
If, for example, transaction is not active, at first there will be an exception on Commit, and then and in handling of this exception - on Rollback, and this second exception you any more do not process.

8

Re: Handling exception in DLL

YuRock wrote:

it is passed...
This strange code only in any single instances can not lead to that the exception does not get "outside".
If, for example, transaction is not active, at first there will be an exception on Commit, and then and in handling of this exception - on Rollback, and this second exception you any more do not process.

Check on activity of transaction above on the code in procedure.

begin
if not Base.itransStoredProc. InTransaction then
Base.itransStoredProc. StartTransaction;
YuRock wrote:

it is passed...
it is passed...
You create. Units, which you use (for example which work with client library FB) is same "your program", as well as personally your code.  differences does not see.

I understand it, meant that I do not create them manually.

9

Re: Handling exception in DLL

Kirill Lagunov wrote:

Check on activity of transaction above on the code in procedure.

Whether Mahlo what there errors

10

Re: Handling exception in DLL

YuRock wrote:

it is passed...
Whether Mahlo what there errors

Error explicit, exception handling by a call of stored procedure which transfers the code and the exception text.
Question then such how it is possible to catch and complete a flow with this exception or how at outswapping DLL to close all flows created by call DLL?

11

Re: Handling exception in DLL

Kirill Lagunov,
In DLL should not arise any exception, it is necessary to envelop a stuffing of each exported function in try. except and to return error status code. And if the error text, then some variants is interesting also: 1) or to add one more function, for example GetLastErrotText, 2) or through function parameters

12

Re: Handling exception in DLL

HostDb: TIBDatabase

You exchange objects Delphi through boundary of units.  to you then DLL?
Do a packet, continuous pluses:
- There are no problems with DllMain, at packets initialization/finalizatsija is carried out in insulated functions
- There are no problems with exceptions through boundaries of units, at packets caused and causing are written in one language
- There are no problems with transmission of storage and crutches are not necessary, packets always implicitly use the divided manager of storage
- The place is saved, the general code is carried out in RTL/VCL packets

13

Re: Handling exception in DLL

Try in  at outswapping to pull

IBSQLMonitor. DisableMonitoring;

14

Re: Handling exception in DLL

Kirill Lagunov wrote:

the Error explicit, exception handling by a call of stored procedure which transfers the code and the exception text.

Well so process it so that at handling there could not be one more exception.

Kirill Lagunov wrote:

the Question then such as it is possible to catch and complete a flow with this exception

Manually and it is more in any way. TIBDatabase flows does not generate, on how many I know. Unless TIBEvents. RegisterEvents
And to do it it is necessary (to stop flows, all objects to release etc.) in . Functions Finalize about which I above wrote.

15

Re: Handling exception in DLL

YuRock wrote:

TIBDatabase flows does not generate, on how many I know

You are mistaken. To smoke IBSQLMonitor.pas

16

Re: Handling exception in DLL

_Vasilisk _;
If monitoring is included, yes. And by default it is ungeared (TraceFlags = []), as well as  by default is not present.

17

Re: Handling exception in DLL

YuRock wrote:

And by default it is ungeared

Ugu. Here only it has property to turn on
[spoiler]

unit IB;
type
TTraceFlag = (tfQPrepare, tfQExecute, tfQFetch, tfError, tfStmt, tfConnect;
tfTransact, tfBlob, tfService, tfMisc);
............
procedure IBDataBaseError (FGDSLibrary: IGDSLibrary);
begin
..........................
if (MonitorHook <> nil) then
MonitorHook. SendError (IntToStr (sqlcode) + ' ' + IntToStr (IBErrorCode) + ' ' + usr_msg);
if sqlcode <>-551 then
raise EIBInterBaseError. Create (sqlcode, IBErrorCode, usr_msg)
else
raise EIBInterBaseRoleError. Create (sqlcode, IBErrorCode, usr_msg)
end;
//=============
unit IBSQLMonitor
...............
function MonitorHook: IIBSQLMonitorHook;
begin
if (_MonitorHook = nil) and (not bDone) then
begin
CS.BeginWrite;
if (_MonitorHook = nil) and (not bDone) then
begin
_MonitorHook: = TIBSQLMonitorHook. Create;
_MonitorHook. _ AddRef;
end;
CS.EndWrite;
end;
result: = _MonitorHook;
end;
constructor TIBSQLMonitorHook. Create;
begin
inherited Create;
FEventsCreated: = false;
==> FTraceFlags: = [tfQPrepare. tfMisc];//Who there that spoke about flags?
==> FEnabled: = true;
end;
procedure TIBSQLMonitorHook. SendError (Msg: String);
begin
if FEnabled then
if (tfError in FTraceFlags) then
WriteSQLData (StrError + Msg, tfError);
end;
procedure TIBSQLMonitorHook. WriteSQLData (Text: String;
DataType: TTraceFlag);
begin
{$IFDEF MSWINDOWS}
if not FEventsCreated then
try
CreateEvents;
except
Enabled: = false;
Exit;
end;
CS.BeginWrite;
Text: = CRLF + StrApplication + DBApplication. Title + '] ' + CRLF + Text; {do not localize}
CS.EndWrite;
if not Assigned (FWriterThread) then
==> FWriterThread: = TWriterThread. Create;//the Surprise!!!
FWriterThread. WriteSQLData (Text, DataType);
{$ENDIF}
end;

[/spoiler]

18

Re: Handling exception in DLL

_Vasilisk _;
Yes, beautifully, certainly. But the such should not reach. I now specially tested. In TWriterThread. Execute and TReaderThread. Execute in debugging I get, only if TIBDatabase. TraceFlags <> []. Did connect, starttransaction, execsql, fetch, commit...
Further to understand laziness. And if it is so, at me all dll, creating inside TIBDatabase, for all life written, would incorrectly be preempted, with problems because of not stopped flows. And it is not present and was never. Only if TIBDatabase not to release - there are problems (too to understand laziness why, after all it is necessary to release all the same).

19

Re: Handling exception in DLL

YuRock wrote:

in debugging I get, only if TIBDatabase. TraceFlags <> []. Did connect, starttransaction, execsql, fetch, commit...

Fulfil ExecSQL but that the operator lifted an error. Something of type

CREATE PROCEDURE sp_except
AS
BEGIN
EXCEPTION my_except;
END

IBSQL1.SQL.Text: = ' EXECUTE PROCEDURE sp_except ';
IBSQL1.ExecQuery;

Or make what  an insertion leading to double unique keys

YuRock wrote:

And if it is so, at me all dll, creating inside TIBDatabase, for all life written, were incorrectly preempted

I on the such came across in the COM-server. If from the server the error (i.e. it is caused IBDataBaseError) application was not preempted comes. In spite of the fact that the exception was intercepted and processed

20

Re: Handling exception in DLL

GunSmoker wrote:

HostDb: TIBDatabase

You exchange objects Delphi through boundary of units.  to you then DLL?
Do a packet, continuous pluses:
- There are no problems with DllMain, at packets initialization/finalizatsija is carried out in insulated functions
- There are no problems with exceptions through boundaries of units, at packets caused and causing are written in one language
- There are no problems with transmission of storage and crutches are not necessary, packets always implicitly use the divided manager of storage
- The place is saved, the general code is carried out in RTL/VCL packets

It is necessary not packets, it is necessary one packet. One bpl, and that many files quit: vcl.bpl, rtl.bpl, forms.bpl, winapi.bpl etc. And that it has been built in in exe, it is desirable. That eyes did not see and not . I would go on a spree: small.dll to the program, and in them as a matter of fact the whole forms. To one   are written specially under application, and 20MB  to recompile each time if not to saw on dll. At me is not present SSD.
try
finally
FreeLibrary (DLLHandle);
end;
^Whether Finally means that  will be preempted without dependence from that was exception. What for it generally to load then? Not for the sake of a call of any function each time.

21

Re: Handling exception in DLL

GunSmoker wrote:

HostDb: TIBDatabase

You exchange objects Delphi through boundary of units.  to you then DLL?
Do a packet, continuous pluses:
- There are no problems with DllMain, at packets initialization/finalizatsija is carried out in insulated functions
- There are no problems with exceptions through boundaries of units, at packets caused and causing are written in one language
- There are no problems with transmission of storage and crutches are not necessary, packets always implicitly use the divided manager of storage
- The place is saved, the general code is carried out in RTL/VCL packets

descriptions of packets wrote:

At usage of packets it is necessary to put all packets to which the packet developed by you refers in the application distribution kit.

If this statement true such variant not especially approaches me.
The library becomes for this purpose that at changes it was not necessary  the main project.

22

Re: Handling exception in DLL

- wrote:

it is passed...
It is necessary not packets, it is necessary one packet. One bpl, and that many files quit: vcl.bpl, rtl.bpl, forms.bpl, winapi.bpl etc. And that it has been built in in exe, it is desirable. That eyes did not see and not . I would go on a spree: small.dll to the program, and in them as a matter of fact the whole forms. To one   are written specially under application, and 20MB  to recompile each time if not to saw on dll. At me is not present SSD.
try
finally
FreeLibrary (DLLHandle);
end;
^Whether Finally means that  will be preempted without dependence from that was exception. What for it generally to load then? Not for the sake of a call of any function each time.

Whether

- wrote:

^Finally means that  will be preempted without dependence from that was exception.

The strange announcement, after all if the library was preempted without dependence from, whether was exception or not, I here would not write smile
And, naturally, not for a call of one function it becomes.
The project enough big, so to say, kol-in ultimate users grows every day, there are different departments at which specific needs to the program, and each time  the main project is not present desire, . it in itself, as a matter of fact, holds all main classes, functions, for operation of the regular employee and as all is made for implementation of dynamic libraries (update/check of a hash and .)

23

Re: Handling exception in DLL

[quote = _ Vasilisk _] it is passed...
You are mistaken. To smoke IBSQLMonitor.pas

The problem appeared too ridiculous, really, is a bug in IBSQLMonitor.
All dared very simply:
The code in DLL

uses..., IBSQLMonitor;
...
function DbInit (DB: TIBDatabase): boolean;
var
i: integer;
begin
result: = false;
if not base.ibcon.connected then
base.ibcon: = db;
try
base.ibcon.connected: = true;
DisableMonitoring;//the Line which solved all problems =)
...

the Source