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:
- The thread Id could have been reused if the original thread has died in between
- 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.