Olivier Sannier wrote:
> I'll try to figure out a way to do this and will submit a patch when I 
> get it working properly.
>   
Ok, figured it out quite easily. Please see the proposed patch at the 
end of this message.
The only question is whether or not I could have read GWndHandleCount 
directly instead of locking GWndHandlerPool and then reading the count 
property of its FList field.

Hope this helps
Cheers
Olivier

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

Index: OverbyteIcsWndControl.pas
===================================================================
--- OverbyteIcsWndControl.pas   (revision 201)
+++ OverbyteIcsWndControl.pas   (working copy)
@@ -287,6 +287,10 @@
   // the GWndHandlerMsgLow + WH_MAX_MSG
   GWndHandlerMsgLow   : Integer;
 
+  // Will be used by the last socket to know if it must cleanup the global
+  // handler because the unit has been finalized before the socket was diposed
+  GUnitFinalized: Boolean;
+
 implementation
 
 // Forward declaration for our Windows callback function
@@ -413,6 +417,23 @@
 {$ENDIF}
 
 
+procedure FinalizeGlobalHandler;
+begin
+    // If the list is empty, we can safely delete the global handler,
+    // else we leave it up to the last socket to do the cleanup
+    GWndHandlerPool.Lock;
+    try
+        if GWndHandlerPool.FList.Count > 0 then
+            Exit;
+    finally
+        GWndHandlerPool.UnLock;
+    end;
+
+    FreeAndNil(GWndHandlerPool);
+    DeleteCriticalSection(GWndHandlerCritSect);
+end;
+
+
 {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
 // MsgHandlersCount _must_ be overriden in derived classes to adjust the number
 // of message handlers needed.
@@ -457,6 +478,20 @@
     if FHandle <> 0 then
         Exit;              // Already done
 
+    // Despite the precautions taken not to destroy GWndHandlerPool via the
+    // finalization when a socket is still there, we could still be going
+    // through this code in the following situation:
+    //
+    //   Application shuts down
+    //   The last known socket frees GWndHandlerPool
+    //   A thread is still running and creates a new socket
+    //
+    // Note that this is highly unlikely, but as a courtesy to developers
+    // we raise an assertion error when this happens.
+    // The solution to this problem is to make sure that all threads are
+    // finished before the application is terminated itself.
+    Assert(Assigned(GWndHandlerPool), 'GWndHandlerPool is already nil, check 
your threads!!!');
+
     FThreadId := GetCurrentThreadId;
     GWndHandlerPool.Lock;
     try
@@ -492,6 +527,9 @@
     finally
         GWndHandlerPool.UnLock;
     end;
+
+    if GUnitFinalized then
+        FinalizeGlobalHandler;
 end;
 
 
@@ -1269,7 +1307,7 @@
     InitializeCriticalSection(GWndHandlerCritSect);
 
 finalization
-    GWndHandlerPool.Free;
-    DeleteCriticalSection(GWndHandlerCritSect);
+    FinalizeGlobalHandler;
+    GUnitFinalized := True;
 
 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

Reply via email to