TROSuperHTTPServer closes SSL connection while SSL_Read is in progress

Hello,

I’m using a TROSuperHTTPServer instance with the appropriate options for it to use OpenSSL and so provide an HTTPs set of services.
Sadly, I’m getting frequent access violations inside this project and after long debugging sessions, I figured out what’s causing them.

Basically, this happens when deactivating the server instance which leads to TROAsyncHTTPServer.SetActive calling DisconnectClients which ultimately calls TROSocketOpenSSL.DeInit which in turn calls SSL_free.
In parallel, there is a TROSocketWorkerThread instance that has called TROAsyncSocket.IntEndReceive which called TROSocketOpenSSL.Read and itself is blocked inside SSL_read

But the OpenSSL documentation is very clear on the subject, SSL_free should never be called when any other operation is in progress on the same PSSL structure.

The SDK does not respect this and it triggers an access violation inside OpenSSL DLL which in my case even kills the entire server because this exception is never caught by any try..except clause.

An unsatisfactory workaround is this, inside TROSocketOpenSSL.DeInit:

  if Assigned(fSSL) then begin
    var curThreadId := GetCurrentThreadId;
    if fSSLThreadId <> curThreadId then
      Sleep(2000);

    SSL_free(fSSL);
    fSSL := nil;
  end;

Basically, I write down the Thread Id that called SSL_new (two locations) and if it is different from the caller thread id, I wait for 2 seconds.
To me, this is not satisfactory for two reasons:

  1. The thread Id could have been reused if the original thread has died in between
  2. The delay is a fixed magic number which makes little sense

The first issue is highly unlikely as the worker thread has no reason to have disappeared before DeInit is called. To be on the safe side, I could open a handle to the thread that called SSL_new and use GetThreadId to do my comparison later on, but it felt too complex for a “workaround”.

For the second issue, I really hope there is another way to write a fix. Note that I thought about an empty try..except around the call to SSL_read but it’s even more disturbing than the hard coded delay. Really, exceptions should never be silently trapped if there is another way.

Hi,

How I can reproduce this case locally?
Do you have steps or testcase for this issue?

You can drop email to support@ for keeping privacy.

Not readily available, not just yet.
But something like this should do:

Server with TROSuperHTTPServer and SSL Enabled with DLLs from Overbyte
Server starts a thread upon startup to set Active to False after a given amount of time.
Client with a channel to that server.
Channel connected used to call one method and left connected

You should see the AV in the server after the server auto closes its connection.

Logged as bugs://D19422.

Of course there is, a simple critical section around any access to FSSL would do.

bugs://D19422 was closed as fixed.

Hi,

you are right