Atozed Forums
Indy TcpSSLServer crashes several times - Printable Version

+- Atozed Forums (https://www.atozed.com/forums)
+-- Forum: Indy (https://www.atozed.com/forums/forum-8.html)
+--- Forum: Indy General Discussion (https://www.atozed.com/forums/forum-9.html)
+--- Thread: Indy TcpSSLServer crashes several times (/thread-2360.html)



Indy TcpSSLServer crashes several times - fpctuxe - 04-09-2021

Hello,


My Indy TcpSSLServer crashes several times. I made a test solution with 1 Server and 5 Clients. Every client has 10 Threads. Each Thread connects, transmits, receives and closes the socket every 2 seconds. After 100000 – 200000 connects, the Server crashes with a memory access error. I found the access error in “IdSSLOpenSSL.pas” in “function TidSSLIOHandlerSocketOpenSSL.Readable”. The SocketClass
“fSSLSocket” was nil. Why? I don’t know.


I changed the source and it works.

function TIdSSLIOHandlerSocketOpenSSL.Readable(AMSec: Integer = IdTimeoutDefault): Boolean;
begin
if not fPassThrough then
begin
// Result := (ssl_pending(fSSLSocket.fSSL) > 0); //Original implementation
Result := Assigned(fSSLSocket) and (ssl_pending(fSSLSocket.fSSL) > 0);
if Result then Exit;
end;
Result := inherited Readable(AMSec);
end;


maybe that will help the users too Smile


My system:
Linux: x86_64
Lazarus: 2.0.10
FPC: 3.2.0
Indy: 10.6.2


RE: Indy TcpSSLServer crashes several times - rlebeau - 04-10-2021

(04-09-2021, 06:47 PM)fpctuxe Wrote: After 100000 – 200000 connects, the Server crashes with a memory access error. I found the access error in “IdSSLOpenSSL.pas” in “function TidSSLIOHandlerSocketOpenSSL.Readable”. The SocketClass “fSSLSocket” was nil. Why? I don’t know.

Likely related to this issue:

https://github.com/IndySockets/Indy/issues/218

When TIdSSLIOHandlerSocketOpenSSL is closed, it destroys its fSSLSocket object, rather than just closing the underlying socket connection but leaving fSSLSocket alive.

(04-09-2021, 06:47 PM)fpctuxe Wrote: I changed the source and it works.

I don't fully agree with that "fix", as it is just a workaround, which introduces a new race condition, and does not really address the root issue. But without a better fix, I have accepted and checked it in for now, thanks.

Another workaround I have considered before, but haven't implemented yet, is to have TIdSSLIOHandlerSocketOpenSSL override the virtual SourceIsAvailable() method to return False when fSSLSocket is nil. TIdIOHandler.ReadFromSource() checks SourceIsAvailable() before and after calling Readable(). But this is also causes a subtle race condition, too.


RE: Indy TcpSSLServer crashes several times - fpctuxe - 04-10-2021

Thanks for the answer.

1.
Yes I think you are right if there is no solution, then there is a workaround. I will test your idea with "SourceIsAvailable ()".

2.
Is it possible that all file descriptors are occupied? I believe that sockets are file descriptors under Linux. My system has 1024 descriptors.


RE: Indy TcpSSLServer crashes several times - fpctuxe - 04-11-2021

So, I have tested the changed with “SourceIsAvailable()”, and it works! I canceled after 1200000 rounds.

Here are the changes:

Back to the original implementation.
function TIdSSLIOHandlerSocketOpenSSL.Readable(AMSec: Integer = IdTimeoutDefault): Boolean;
begin
if not fPassThrough then
begin
Result := (ssl_pending(fSSLSocket.fSSL) > 0);
if Result then Exit;
end;
Result := inherited Readable(AMSec);
end;

New.
definition
protected
function TIdSSLIOHandlerSocketOpenSSL.SourceIsAvailable: Boolean; override;

implementation
function TIdSSLIOHandlerSocketOpenSSL.SourceIsAvailable: Boolean;
begin
Result:=Assigned(fSSLSocket) and inherited SourceIsAvailable;
end;

that's all.

Thanks for support.


RE: Indy TcpSSLServer crashes several times - rlebeau - 04-12-2021

(04-11-2021, 01:34 PM)fpctuxe Wrote: function TIdSSLIOHandlerSocketOpenSSL.SourceIsAvailable: Boolean;
begin
  Result:=Assigned(fSSLSocket) and inherited SourceIsAvailable;
end;

I was thinking more along the lines of:

Code:
function TIdSSLIOHandlerSocketOpenSSL.SourceIsAvailable: Boolean;
begin
  if not fPassThrough then
  begin
    Result := (fSSLSocket <> nil);
    if not Result then Exit;
  end;
  Result := inherited SourceIsAvailable;
end;


Or:

Code:
function TIdSSLIOHandlerSocketOpenSSL.SourceIsAvailable: Boolean;
begin
  if (fPassThrough or (fSSLSocket <> nil)) and inherited SourceIsAvailable;
end;



RE: Indy TcpSSLServer crashes several times - fpctuxe - 04-28-2021

Hello, I thing you mean this

Code:
function TIdSSLIOHandlerSocketOpenSSL.SourceIsAvailable: Boolean;
begin
  Result:= (fPassThrough or (fSSLSocket <> nil)) and inherited SourceIsAvailable;
end;

So, I have long time tested the changed with “SourceIsAvailable()”, and it works!

Than I have tested the Accept method to check is fSSLSocket = NIL. Without the new changes.

But on the moment how the mistake occurs, fSSLSocket was created. In the moment, I wand live with the workaround.

Thanks for your help.