I got a report today that the `ioReactorExceptionCallback` is firing due to a socket timeout:
java.net.SocketTimeoutException: 2500 MILLISECONDS at org.apache.hc.core5.io.SocketTimeoutExceptionFactory.create(SocketTimeoutExceptionFactory.java:50) at org.apache.hc.core5.reactor.ssl.SSLIOSession$1.timeout(SSLIOSession.java:223) at org.apache.hc.core5.reactor.InternalDataChannel.onTimeout(InternalDataChannel.java:170) at org.apache.hc.core5.reactor.InternalChannel.checkTimeout(InternalChannel.java:67) at org.apache.hc.core5.reactor.SingleCoreIOReactor.checkTimeout(SingleCoreIOReactor.java:239) at org.apache.hc.core5.reactor.SingleCoreIOReactor.validateActiveChannels(SingleCoreIOReactor.java:166) at org.apache.hc.core5.reactor.SingleCoreIOReactor.doExecute(SingleCoreIOReactor.java:128) at org.apache.hc.core5.reactor.AbstractSingleCoreIOReactor.execute(AbstractSingleCoreIOReactor.java:92) at org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.java:44) at java.base/java.lang.Thread.run(Thread.java:840) Based on the code and the stack trace, 2500 milliseconds is actually the connection timeout and thus the TLS handshake timeout. This is reproducible in TestAsyncTlsHandshakeTimeout by setting `HttpVersionPolicy.FORCE_HTTP_2` (but _not_ `NEGOTIATE`). I traced this change in behavior back to the following commit: https://github.com/apache/httpcomponents-core/commit/be9902826576413c694c59cc582fc38db8aeb772 This is a regression, as the contract for `setIoReactorExceptionCallback()` is that it sets a callback for exceptions that propagate all the way through the IOReactor *and kill the client*. The default behavior (cf. LoggingExceptionCallback) is to log an ERROR, which is bad enough, but in our case we supply a custom callback that logs a FATAL, which then triggers alarms and stuff. How should we address this? What types of exceptions were intended to be reported by be9902826? We probably (1) want to use a different exception callback for these exceptions and (2) want to fire the callback only for unexpected (internal) exceptions and not things like timeouts. It's also possible that this exception callback should fire when `HttpVersionPolicy.NEGOTIATE` is used; it currently doesn't, which may also be a bug.
