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