Hello Olivier,

Thank you for your analysis.
Initialization/finalization order has always been an issue, no matter which
component you use.
Developer has control on it ! Finalization sections are executed in the
reverse order of their initialization section which in turn are executed in
the order of their enumeration in the uses clause. So for your problem, if
you add OverbyteIcsWndControl in front (well after other higher priority
units such as FastMM4) of the dpr uses clause, the issue should go away.
Please check and tell me what.

About your changes: It's sure that using FreeAndNil is a good idea. Checking
Assigned(GWndHandlerPool) is also good but be aware that this would hide the
exception and still may produce unexpected results since the lock is no more
used. If you some reason a thread is still working and using the same code
section, you'll be in trouble. Granted this is not common situation.

--
[EMAIL PROTECTED]
Author of ICS (Internet Component Suite, freeware)
Author of MidWare (Multi-tier framework, freeware)
http://www.overbyte.be

----- Original Message ----- 
From: "Olivier Sannier" <[EMAIL PROTECTED]>
To: "ICS support mailing" <twsocket@elists.org>
Sent: Friday, October 10, 2008 10:13 AM
Subject: [twsocket] GWndHandlerPool is freed before sockets are destroyed


Hi,

I just ported an application to ICSv6 and I'm encountering a problem
when closing it down. It gives me an access violation in ntdll.dll,
write of address 00000010
Digging around, I discovered that it comes from the call to
GWndHandlerPool.Lock inside TIcsWndControl.DeallocateHWnd
At the time it is being called, GWndHandlerPool has already been freed
by the finalization section of OverbyteIcsWndControl.pas which ran
before my own finalization section.
In my own section, I'm freeing, indirectly, a class that contains a
TWSocketServer which not active.
I know this comes from the indirect nature of my usage of the class, but
still, the order of finalization clauses should not be relied upon, as
it was always indicated by the Delphi team. In particular, it will be
different and changing when using packages.
I tried this with ICSv7, it shows the same behavior.
I thus propose to FreeAndNil GWndHandlerPool  instead of simply freeing
it, and then test if it is Assigned in all places it can be used (or the
associated GWndHandlerCritSect section) when deallocating the window handle.
I placed a "TortoiseSVN" patch file at the end of this message, you
should be able to paste it into a blank .patch file and apply it to the
current version of ICS.

Please let me know what you think, right now this issue is blocking my
upgrade.

Cheers
Olivier

////////////////////////////////////////////////////////////////////////////
////////////////

Index: OverbyteIcsWndControl.pas
===================================================================
--- OverbyteIcsWndControl.pas    (revision 34841)
+++ OverbyteIcsWndControl.pas    (working copy)
@@ -481,16 +481,18 @@
     if FHandle = 0 then
         Exit;              // Already done

-    GWndHandlerPool.Lock;
+    if Assigned(GWndHandlerPool) then
+        GWndHandlerPool.Lock;
     try
         FreeMsgHandlers;
-        if Assigned(FWndHandler) and (FWndHandler.FMsgCnt <= 0) then
+        if Assigned(FWndHandler) and (FWndHandler.FMsgCnt <= 0) and
Assigned(GWndHandlerPool) then
             GWndHandlerPool.FreeWndHandler(FWndHandler);
         FHandle     := 0;
         FWndHandler := nil;
         FThreadID   := 0;
     finally
-        GWndHandlerPool.UnLock;
+        if Assigned(GWndHandlerPool) then
+            GWndHandlerPool.UnLock;
     end;
 end;

@@ -877,7 +879,8 @@
     DestroyWindow(FHandle);       // Détruit la fenêtre cachée
     FHandle := 0;                 // On n'a plus de handle !

-    EnterCriticalSection(GWndHandlerCritSect);
+    if Assigned(GWndHandlerPool) then
+        EnterCriticalSection(GWndHandlerCritSect);
     try
         Dec(GWndHandleCount);
         if GWndHandleCount <= 0 then
@@ -888,7 +891,8 @@
             OverbyteIcsLibrary.UnregisterClass(
                 IcsWndControlWindowClassName, HInstance);
     finally
-        LeaveCriticalSection(GWndHandlerCritSect);
+        if Assigned(GWndHandlerPool) then
+            LeaveCriticalSection(GWndHandlerCritSect);
     end;
 end;
 {$ENDIF}
@@ -1269,7 +1273,7 @@
     InitializeCriticalSection(GWndHandlerCritSect);

 finalization
-    GWndHandlerPool.Free;
+    FreeAndNil(GWndHandlerPool);
     DeleteCriticalSection(GWndHandlerCritSect);

 end.


-- 
To unsubscribe or change your settings for TWSocket mailing list
please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

-- 
To unsubscribe or change your settings for TWSocket mailing list
please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

Reply via email to