On Wed, 2026-01-21 at 19:36 -0800, Ryan Schmitt wrote: > I've updated TestAsyncTlsHandshakeTimeout to reproduce this bug. > Specifically, see the two test cases that use FORCE_HTTP_2 (they will > be > marked as ignored in the test report, but they still run). >
Hi Ryan, I introduced the exception callback to the protocol negotiators to ensure there is a means of signaling unexpected exceptions before a protocol handler could be negotiated and activated. Prior to this change HttpClient could just quietly go down without reporting _any_ problem at all in case of an unexpected error during protocol negotiation handshake. However, it is likely I got the exception handling of i/o errors wrong. I will look into it. Oleg > On Wed, Jan 21, 2026 at 3:13 PM Ryan Schmitt <[email protected]> > wrote: > > > 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(SocketT > > imeoutExceptionFactory.java:50) > > at > > org.apache.hc.core5.reactor.ssl.SSLIOSession$1.timeout(SSLIOSession > > .java:223) > > at > > org.apache.hc.core5.reactor.InternalDataChannel.onTimeout(InternalD > > ataChannel.java:170) > > at > > org.apache.hc.core5.reactor.InternalChannel.checkTimeout(InternalCh > > annel.java:67) > > at > > org.apache.hc.core5.reactor.SingleCoreIOReactor.checkTimeout(Single > > CoreIOReactor.java:239) > > at > > org.apache.hc.core5.reactor.SingleCoreIOReactor.validateActiveChann > > els(SingleCoreIOReactor.java:166) > > at > > org.apache.hc.core5.reactor.SingleCoreIOReactor.doExecute(SingleCor > > eIOReactor.java:128) > > at > > org.apache.hc.core5.reactor.AbstractSingleCoreIOReactor.execute(Abs > > tractSingleCoreIOReactor.java:92) > > at > > org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.jav > > a: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. > > --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
