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]

Reply via email to