[twsocket] Threaded TWSocketServer derivation

2005-11-04 Thread Arno Garrels
Hello,

After a big fight with deadlocks and race conditions for one day my
threaded TWSocketServer derivation is now working stable. 
(tested with Wilfrieds GPRS Client and other stressing clients)
But.. I have still a tiny problem with ThreadDetach.
An AV is sometimes raised (see MadExcept trace below) from within
the Execute procedure when csDestroying is in client's ComponentState.
I can work around that by checking for (Client.ComponentState = [])
but I don't think it's good practice. It happens only when the
destructor is called and a lot of threads are busy. 

Any idea?

---
Arno Garrels [TeamICS]


 
Destructor of TThrdWSocketServer terminates the threads:

for I := 0 to FThreadList.Count -1 do
begin
AThread := TThread(FThreadList[I]);
if PostThreadMessage(AThread.ThreadID, WM_THREAD_TERMINATE, 0, 0) then
begin
Dec(FThreadCount);
Sleep(0);
end;
end;

WM_THREAD_TERMINATE exits PumpMessages()

procedure TWSClientThread.Execute;
var
I  : Integer;
Client : TThrdWSocketClient;
Msg: TMsg;
begin
try
{ Initialize thread's message queue }
PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE);
SetEvent(EventArray[THREAD_READY_EVENT]);
FReadyForMsgs := TRUE;
FClients := TList.Create;
try
PumpMessages(True);
if not Terminated then
Terminate;
InterlockedDecrement(FServer.FThreadCount);
for I := 0 to FClients.Count -1 do 
begin
Client := FClients[I];
if Assigned(Client) then
Client.ThreadDetach; = *AV here
end;
finally
FClients.Free;
FClients := nil;
end;
finally
PostMessage(FServer.Handle, WM_THREAD_TERMINATED, Integer(Self), 0);
{ Just to make sure the  main thread isn't waiting for this thread }
{ signal the events }
SetEvent(EventArray[CLIENT_REMOVED_EVENT]);
SetEvent(EventArray[CLIENT_ATTACHED_EVENT]);
end;
end; 
 

exception class   : EAccessViolation
exception message : Accessviolation at Address 0048C6C9 in Module 'TcpSrv.exe'. 
Read from Address 0038.

thread $26c (TWsClientThread):
0048c6c9 TcpSrv.exe WSocket4159 TCustomWSocket.ThreadDetach
00495706 TcpSrv.exe WSocketS906 TWsClientThread.Execute
00442a36 TcpSrv.exe Classes9372 ThreadProc
004049dc TcpSrv.exe System11554 ThreadWrapper
0042bcbb TcpSrv.exe madExcept   ThreadExceptFrame
 created by main thread ($6ec) at:
0049539a TcpSrv.exe WSocketS787 TWsClientThread.Create

main thread ($6ec):
7c91eb94 ntdll.dll  KiFastSystemCallRet
7c91e64c ntdll.dll  NtSetInformationThread

thread $3fc: priority:1
7c91eb94 ntdll.dll  KiFastSystemCallRet
7c91e319 ntdll.dll  NtRemoveIoCompletion

thread $314:
 stack not accessible

thread $798:
 stack not accessible

thread $778:
 stack not accessible

thread $90 (TWsClientThread):
7c91eb94 ntdll.dllKiFastSystemCallRet
7c91e9be ntdll.dllNtWaitForSingleObject
7c8025d5 kernel32.dll WaitForSingleObjectEx
7c80253d kernel32.dll WaitForSingleObject
00426e8a TcpSrv.exe   madExcept   HandleException
0042bd4d TcpSrv.exe   madExcept   HookedTThreadExecute
7c91eaf5 ntdll.dllKiUserExceptionDispatcher
0048c6c9 TcpSrv.exe   WSocket4159 TCustomWSocket.ThreadDetach
00495706 TcpSrv.exe   WSocketS906 TWsClientThread.Execute
00442a36 TcpSrv.exe   Classes9372 ThreadProc
004049dc TcpSrv.exe   System11554 ThreadWrapper
0042bcbb TcpSrv.exe   madExcept   ThreadExceptFrame
 created by main thread ($6ec) at:
0049539a TcpSrv.exe   WSocketS787 TWsClientThread.Create

thread $728:
 stack not accessible

thread $374 (TWsClientThread):
7c91eb94 ntdll.dllKiFastSystemCallRet
7c91e9be ntdll.dllNtWaitForSingleObject
7c8025d5 kernel32.dll WaitForSingleObjectEx
7c80253d kernel32.dll WaitForSingleObject
00426e8a TcpSrv.exe   madExcept   HandleException
0042bd4d TcpSrv.exe   madExcept   HookedTThreadExecute
7c91eaf5 ntdll.dllKiUserExceptionDispatcher
0042bd26 TcpSrv.exe   madExcept   HookedTThreadExecute
00442a36 TcpSrv.exe   Classes9372 ThreadProc
004049dc TcpSrv.exe   System11554 ThreadWrapper
0042bcbb TcpSrv.exe   madExcept   ThreadExceptFrame
 created by main thread ($6ec) at:
0049539a TcpSrv.exe   WSocketS787 TWsClientThread.Create

disassembling:
0048c67c  public WSocket.TCustomWSocket.ThreadDetach:  ; function entry 
point
0048c67c 4153   pushebp
0048c67dmov ebp, esp
0048c67fpushecx
0048c680mov [ebp-4], eax
0048c683 4154   call-$85750 ($406f38)  ; Windows.GetCurrentThreadId
0048c683
0048c688mov edx, [ebp-4]
0048c68bcmp eax, [edx+$548]
0048c691jz  loc_48c6a0

Re: [twsocket] Threaded TWSocketServer derivation

2005-11-04 Thread Francois Piette
Isn't it possible that the client is already destroyed when you call 
ThreadDetech ? If yes,
accessing self in ThreadDetach cause the access violation.

Each time a client is freed, it must be remove from the list to avoid this 
problem.

--
Contribute to the SSL Effort. Visit
http://www.overbyte.be/eng/ssl.html
--
[EMAIL PROTECTED]
Author of ICS (Internet Component Suite, freeware)
Author of MidWare (Multi-tier framework, freeware)
http://www.overbyte.be



- Original Message - 
From: Arno Garrels [EMAIL PROTECTED]
To: ICS support mailing twsocket@elists.org
Sent: Friday, November 04, 2005 12:14 PM
Subject: [twsocket] Threaded TWSocketServer derivation


 Hello,

 After a big fight with deadlocks and race conditions for one day my
 threaded TWSocketServer derivation is now working stable.
 (tested with Wilfrieds GPRS Client and other stressing clients)
 But.. I have still a tiny problem with ThreadDetach.
 An AV is sometimes raised (see MadExcept trace below) from within
 the Execute procedure when csDestroying is in client's ComponentState.
 I can work around that by checking for (Client.ComponentState = [])
 but I don't think it's good practice. It happens only when the
 destructor is called and a lot of threads are busy.

 Any idea?

 ---
 Arno Garrels [TeamICS]



 Destructor of TThrdWSocketServer terminates the threads:

 for I := 0 to FThreadList.Count -1 do
 begin
 AThread := TThread(FThreadList[I]);
 if PostThreadMessage(AThread.ThreadID, WM_THREAD_TERMINATE, 0, 0) then
 begin
 Dec(FThreadCount);
 Sleep(0);
 end;
 end;

 WM_THREAD_TERMINATE exits PumpMessages()

 procedure TWSClientThread.Execute;
 var
 I  : Integer;
 Client : TThrdWSocketClient;
 Msg: TMsg;
 begin
 try
 { Initialize thread's message queue }
 PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE);
 SetEvent(EventArray[THREAD_READY_EVENT]);
 FReadyForMsgs := TRUE;
 FClients := TList.Create;
 try
 PumpMessages(True);
 if not Terminated then
 Terminate;
 InterlockedDecrement(FServer.FThreadCount);
 for I := 0 to FClients.Count -1 do
 begin
 Client := FClients[I];
 if Assigned(Client) then
 Client.ThreadDetach; = *AV here
 end;
 finally
 FClients.Free;
 FClients := nil;
 end;
 finally
 PostMessage(FServer.Handle, WM_THREAD_TERMINATED, Integer(Self), 0);
 { Just to make sure the  main thread isn't waiting for this thread }
 { signal the events }
 SetEvent(EventArray[CLIENT_REMOVED_EVENT]);
 SetEvent(EventArray[CLIENT_ATTACHED_EVENT]);
 end;
 end;


 exception class   : EAccessViolation
 exception message : Accessviolation at Address 0048C6C9 in Module 
 'TcpSrv.exe'. Read from Address
0038.

 thread $26c (TWsClientThread):
 0048c6c9 TcpSrv.exe WSocket4159 TCustomWSocket.ThreadDetach
 00495706 TcpSrv.exe WSocketS906 TWsClientThread.Execute
 00442a36 TcpSrv.exe Classes9372 ThreadProc
 004049dc TcpSrv.exe System11554 ThreadWrapper
 0042bcbb TcpSrv.exe madExcept   ThreadExceptFrame
  created by main thread ($6ec) at:
 0049539a TcpSrv.exe WSocketS787 TWsClientThread.Create

 main thread ($6ec):
 7c91eb94 ntdll.dll  KiFastSystemCallRet
 7c91e64c ntdll.dll  NtSetInformationThread

 thread $3fc: priority:1
 7c91eb94 ntdll.dll  KiFastSystemCallRet
 7c91e319 ntdll.dll  NtRemoveIoCompletion

 thread $314:
  stack not accessible

 thread $798:
  stack not accessible

 thread $778:
  stack not accessible

 thread $90 (TWsClientThread):
 7c91eb94 ntdll.dllKiFastSystemCallRet
 7c91e9be ntdll.dllNtWaitForSingleObject
 7c8025d5 kernel32.dll WaitForSingleObjectEx
 7c80253d kernel32.dll WaitForSingleObject
 00426e8a TcpSrv.exe   madExcept   HandleException
 0042bd4d TcpSrv.exe   madExcept   HookedTThreadExecute
 7c91eaf5 ntdll.dllKiUserExceptionDispatcher
 0048c6c9 TcpSrv.exe   WSocket4159 TCustomWSocket.ThreadDetach
 00495706 TcpSrv.exe   WSocketS906 TWsClientThread.Execute
 00442a36 TcpSrv.exe   Classes9372 ThreadProc
 004049dc TcpSrv.exe   System11554 ThreadWrapper
 0042bcbb TcpSrv.exe   madExcept   ThreadExceptFrame
  created by main thread ($6ec) at:
 0049539a TcpSrv.exe   WSocketS787 TWsClientThread.Create

 thread $728:
  stack not accessible

 thread $374 (TWsClientThread):
 7c91eb94 ntdll.dllKiFastSystemCallRet
 7c91e9be ntdll.dllNtWaitForSingleObject
 7c8025d5 kernel32.dll WaitForSingleObjectEx
 7c80253d kernel32.dll WaitForSingleObject
 00426e8a TcpSrv.exe   madExcept   HandleException
 0042bd4d TcpSrv.exe   madExcept   HookedTThreadExecute
 7c91eaf5 ntdll.dll   

Re: [twsocket] Threaded TWSocketServer derivation

2005-11-04 Thread Arno Garrels
Francois Piette wrote:
 Isn't it possible that the client is already destroyed when you call
 ThreadDetech ? If yes, accessing self in ThreadDetach cause the access
 violation.

Yes, very simple, that seems to be the reason. I think I've fixed it by
just waiting for all threads return and being freed manually in the main
thread before going ahead in the destructor.
Sometimes, when bugs are too obvious I don't find them :(

---
Arno Garrels [TeamICS]



-- 
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


Re: [twsocket] Fw: TCustomSmtpClient.AuthGetType

2005-11-04 Thread Arno Garrels
 From: Vander Clock Stephane
[..]
 I think you must replace
 S := Copy(S, 5, Length(S));
 
 by
 S := Copy(S, 6, Length(S));

I don't know why,  length of both strings is 5 not 6.

Typically the lines in question of a EHLO response look like
250-AUTH=LOGIN CRAM-MD5 PLAIN
250-AUTH CRAM-MD5 LOGIN PLAIN

---
Arno Garrels [TeamICS]
-- 
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


Re: [twsocket] Fw: TCustomSmtpClient.AuthGetType

2005-11-04 Thread DZ-Jay
DZ-Jay wrote:
 since the CompareText calls Copy() with an Index of 
 1, which means that it starts to delete at the second character, not to 
 mention the call to Delete() uses an Index of 1 also.

This should have been:

  which means that it starts to copy at the second character...

Sorry,
dZ.
-- 
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