Francois Piette wrote:
>> When I destroy the SimpleThrdSslServer with alot of threads and clients
>> I can avoid AV's by this code:
>> 
>> function TCustomWSocket.TriggerDataAvailable(Error : Word) : Boolean;
>> begin
>>     Result := Assigned(FOnDataAvailable) and not (csDestroying in
>> ComponentState);     if not Result then
>>         Exit;
>> ...
> 
> At first glance, I don't see why this code would cause trouble in
> existing application. But why don't put it in the application code ?

Because I think that DataAvailable should not be triggered when the 
component is destroyed anyway, but I may be wrong. 

I've played with the TWSocketThrdServer and modified it to always 
wait for the threads, now FreeOnTerminate is _always_ set to FALSE.
You know that the threads post WM_THREAD_TERMINATED at the end of
method execute to the server window. So, in destructor messages must
be processed. If you have a better idea please let me know.
May be this is the reason why I get random AV's in OnDataAvailable.
Note that I'm stress-testing with a client that connects, sends
a request and server echos the request, this all very fast, one
after the another, until there are up to thousand concurrent
connections.


procedure TWSocketThrdServer.WmThreadTerminated(var Msg: TMessage);
var
    AThread : TWsClientThread;
    I      : Integer;
begin
    AThread := TObject(Msg.WParam) as TWsClientThread;
    I := FThreadList.IndexOf(AThread);
    if I > -1 then
        FThreadList.Delete(I);
    AThread.WaitFor;
    if Assigned(FOnBeforeThreadDestroy) then
        FOnBeforeThreadDestroy(Self, AThread);
    if not AThread.FreeOnTerminate then
        AThread.Destroy;
end;


{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TWSocketThrdServer.TerminateThreads;
var
    AThread : TWsClientThread;
    I       : Integer;
begin
    for I := 0 to FThreadList.Count - 1 do begin
        AThread := TWsClientThread(FThreadList[I]);
        if PostThreadMessage(AThread.ThreadID,
                             WM_THREAD_TERMINATE, 0, 0) then begin
            InterlockedDecrement(FThreadCount);
            Sleep(0);
        end;
    end;
end;


destructor TWSocketThrdServer.Destroy;
var
    WaitRes : LongWord;
    Dummy   : Byte;
    Msg     : tagMsg;
begin
    Pause; // while waiting for our threads don't accept new clients!!
    TerminateThreads;
    try
        if FThreadList.Count > 0 then
        repeat
            WaitRes := MsgWaitForMultipleObjects(0, Dummy, FALSE, 500,
                                             QS_POSTMESSAGE or QS_SENDMESSAGE);
            if WaitRes = WAIT_FAILED then
                raise Exception.Create('Wait for threads failed ' +
                                       SysErrorMessage(GetLastError))
            else if WaitRes = WAIT_OBJECT_0 then
                while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
                begin
                    TranslateMessage(Msg);
                    DispatchMessage(Msg);
                end;
        until FThreadList.Count = 0;
    finally
        inherited Destroy;
        FreeAndNil(FThreadList);        
    end;
end;

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

Reply via email to