Когда Putty подключен в режиме Raw, рукопожатие SSL / TLS не выполняется, поэтому SSL_accept()
застревает в ожидании запроса на подтверждение связи, который никогда не приходит.
Когда TIdTCPServer
деактивируется, он отключает активные соединения с сокетами, не выполняя любые операции блокирования сокетов, выполняемые в других потоках. В случае SSL_accept()
это должно разблокировать его, чтобы он мог выйти с кодом ошибки, который TIdSSLSocket.Accept()
может затем обнаружить и обернуть в повышенное исключение (EIdOSSLUnderlyingCryptoError
, EIdOSSLAcceptError
, EIdSocketError
и т. Д. В зависимости от природа кода ошибки) в контексте клиентского потока, ожидающего завершения рукопожатия.
Однако, когда TIdTCPServer
отключает соединение с сокетом во время деактивации, вызывается TIdTCPConnection.Disconnect()
, который вызывает TIdIOHandler.Close()
, который TIdSSLIOhandlerSocketOpenSSL
переопределил для освобождения своего внутреннего объекта TIdSSLSocket
- того же самого объекта, который вызывает SSL_accept()
. Таким образом, вполне вероятно, что базовый объект OpenSSL SSL
освобождается в TIdSSLSocket.Destroy()
(который вызывает SSL_shutdown()
и SSL_free()
) в контексте деактивирующего потока, при этом все еще активно используется в TIdSSLObject.Accept()
(который вызывает SSL_accept()
) в контексте клиентского потока, что приводит к нарушению прав доступа.
Ничего не поделаешь, не изменив исходный код Indy. Например, возможно, замените TIdCustomTCPServer.DoTerminateContext()
на AContext.Binding.CloseSocket()
вместо AContext.Connection.Disconnect(False)
, чтобы сам IOHandler
не был закрыт, а только нижележащим сокетом (аналогично тому, что TIdCustomTCPServer.StopListening()
делает при завершении прослушивания потоков accept()
).
Я открыл для вас билет в трекере Indy:
# 218: нарушение прав доступа в SSL_accept () при деактивации TIdTCPServer