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