Hi,
I can't pinpoint since when this started, but SSL based tests are really flaky on my machine. Mostly when run in the whole suite and not when run in isolation. E.g. the following tests fail relatively frequent:
org.springframework.boot.rsocket.netty.NettyRSocketServerFactoryTests > tcpTransportBasicSslFromClassPath()
org.springframework.boot.rsocket.netty.NettyRSocketServerFactoryTests > tcpTransportBasicSslFromFileSystem()
org.springframework.boot.rsocket.netty.NettyRSocketServerFactoryTests > websocketTransportBasicSslFromClassPath()
org.springframework.boot.rsocket.netty.NettyRSocketServerFactoryTests > websocketTransportBasicSslFromFileSystem()
org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactoryTests > basicSslFromClassPath()
org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactoryTests > basicSslFromFileSystem()
org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactoryTests > sslNeedsClientAuthenticationSucceedsWithClientCertificate()
org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactoryTests > sslWantsClientAuthenticationSucceedsWithClientCertificate()
org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactoryTests > sslWantsClientAuthenticationSucceedsWithoutClientCertificate()
org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactoryTests > sslWithValidAlias()
org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactoryTests > whenSslIsConfiguredWithAValidAliasARequestSucceeds()
org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactoryTests > sslWantsClientAuthenticationSucceedsWithoutClientCertificate()
I'm mostly running on JDK 11 btw, but I'm doing that for over a year or longer and never experienced that.
An example stacktrace:
java.lang.AssertionError: expectation "expectNext(test payload)" failed (expected: onNext(test payload); actual: onError(java.nio.channels.ClosedChannelException))
at reactor.test.MessageFormatter.assertionError(MessageFormatter.java:115)
at reactor.test.MessageFormatter.failPrefix(MessageFormatter.java:104)
at reactor.test.MessageFormatter.fail(MessageFormatter.java:73)
at reactor.test.MessageFormatter.failOptional(MessageFormatter.java:88)
at reactor.test.DefaultStepVerifierBuilder.lambda$addExpectedValue$10(DefaultStepVerifierBuilder.java:501)
at reactor.test.DefaultStepVerifierBuilder$SignalEvent.test(DefaultStepVerifierBuilder.java:2212)
at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onSignal(DefaultStepVerifierBuilder.java:1484)
at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onExpectation(DefaultStepVerifierBuilder.java:1432)
at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onError(DefaultStepVerifierBuilder.java:1091)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onError(FluxMapFuseable.java:140)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onError(FluxMapFuseable.java:140)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at io.rsocket.core.ResolvingOperator$DeferredResolution.onError(ResolvingOperator.java:476)
at io.rsocket.core.DefaultRSocketClient$FlattingInner.accept(DefaultRSocketClient.java:410)
at io.rsocket.core.DefaultRSocketClient$FlattingInner.accept(DefaultRSocketClient.java:366)
at io.rsocket.core.ResolvingOperator.terminate(ResolvingOperator.java:206)
at io.rsocket.core.DefaultRSocketClient.onError(DefaultRSocketClient.java:164)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:172)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:172)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onError(FluxMapFuseable.java:140)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onError(FluxMapFuseable.java:140)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onError(FluxMapFuseable.java:140)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:392)
at reactor.core.publisher.MonoCreate$DefaultMonoSink.error(MonoCreate.java:189)
at reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.onUncaughtException(DefaultPooledConnectionProvider.java:219)
at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnection.onUncaughtException(DefaultPooledConnectionProvider.java:468)
at reactor.netty.channel.ChannelOperationsHandler.exceptionCaught(ChannelOperationsHandler.java:130)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:302)
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:281)
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:273)
at reactor.netty.tcp.SslProvider$SslReadHandler.userEventTriggered(SslProvider.java:832)
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:346)
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:332)
at io.netty.channel.AbstractChannelHandlerContext.fireUserEventTriggered(AbstractChannelHandlerContext.java:324)
at io.netty.handler.ssl.SslUtils.handleHandshakeFailure(SslUtils.java:441)
at io.netty.handler.ssl.SslHandler.setHandshakeFailure(SslHandler.java:1798)
at io.netty.handler.ssl.SslHandler.channelInactive(SslHandler.java:1066)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)
at io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:831)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:497)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:831)
Suppressed: java.nio.channels.ClosedChannelException
at io.netty.handler.ssl.SslHandler.channelInactive(SslHandler.java:1063)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Assembly trace from producer [reactor.core.publisher.MonoCreate] :
reactor.core.publisher.Mono.create
reactor.netty.resources.PooledConnectionProvider.acquire(PooledConnectionProvider.java:112)
Error has been observed at the following site(s):
|_ Mono.create ⇢ at reactor.netty.resources.PooledConnectionProvider.acquire(PooledConnectionProvider.java:112)
|_ Mono.create ⇢ at reactor.netty.resources.PooledConnectionProvider.acquire(PooledConnectionProvider.java:112)
|_ ⇢ at reactor.netty.tcp.TcpResources.acquire(TcpResources.java:162)
|_ ⇢ at reactor.netty.tcp.TcpResources.acquire(TcpResources.java:162)
|_ Mono.map ⇢ at io.rsocket.transport.netty.client.TcpClientTransport.connect(TcpClientTransport.java:119)
|_ Mono.map ⇢ at io.rsocket.transport.netty.client.TcpClientTransport.connect(TcpClientTransport.java:119)
|_ ⇢ at io.rsocket.core.RSocketConnector.lambda$null$5(RSocketConnector.java:525)
|_ ⇢ at io.rsocket.core.RSocketConnector.lambda$null$5(RSocketConnector.java:525)
|_ Mono.flatMap ⇢ at io.rsocket.core.RSocketConnector.lambda$connect$15(RSocketConnector.java:525)
|_ Mono.flatMap ⇢ at io.rsocket.core.RSocketConnector.lambda$connect$15(RSocketConnector.java:525)
|_ Mono.map ⇢ at io.rsocket.core.RSocketConnector.lambda$connect$15(RSocketConnector.java:526)
|_ Mono.map ⇢ at io.rsocket.core.RSocketConnector.lambda$connect$15(RSocketConnector.java:526)
|_ Mono.map ⇢ at io.rsocket.core.RSocketConnector.lambda$connect$15(RSocketConnector.java:530)
|_ Mono.map ⇢ at io.rsocket.core.RSocketConnector.lambda$connect$15(RSocketConnector.java:530)
|_ Mono.flatMap ⇢ at io.rsocket.core.RSocketConnector.lambda$connect$15(RSocketConnector.java:533)
|_ Mono.flatMap ⇢ at io.rsocket.core.RSocketConnector.lambda$connect$15(RSocketConnector.java:533)
|_ Mono.flatMap ⇢ at io.rsocket.core.RSocketConnector.lambda$connect$15(RSocketConnector.java:540)
|_ Mono.flatMap ⇢ at io.rsocket.core.RSocketConnector.lambda$connect$15(RSocketConnector.java:540)
|_ Mono.flatMap ⇢ at io.rsocket.core.RSocketConnector.connect(RSocketConnector.java:515)
|_ Mono.flatMap ⇢ at io.rsocket.core.RSocketConnector.connect(RSocketConnector.java:515)
|_ ⇢ at io.rsocket.core.RSocketConnector.connect(RSocketConnector.java:501)
|_ ⇢ at io.rsocket.core.RSocketConnector.connect(RSocketConnector.java:501)
|_ ⇢ at io.rsocket.core.DefaultRSocketClient.unwrapReconnectMono(DefaultRSocketClient.java:78)
|_ ⇢ at io.rsocket.core.DefaultRSocketClient.unwrapReconnectMono(DefaultRSocketClient.java:78)
|_ ⇢ at io.rsocket.core.DefaultRSocketClient.requestResponse(DefaultRSocketClient.java:93)
|_ ⇢ at io.rsocket.core.DefaultRSocketClient.requestResponse(DefaultRSocketClient.java:93)
|_ Mono.map ⇢ at org.springframework.messaging.rsocket.DefaultRSocketRequester$DefaultRequestSpec.retrieveMono(DefaultRSocketRequester.java:289)
|_ Mono.map ⇢ at org.springframework.messaging.rsocket.DefaultRSocketRequester$DefaultRequestSpec.retrieveMono(DefaultRSocketRequester.java:289)
|_ Mono.map ⇢ at org.springframework.messaging.rsocket.DefaultRSocketRequester$DefaultRequestSpec.retrieveMono(DefaultRSocketRequester.java:290)
|_ Mono.map ⇢ at org.springframework.messaging.rsocket.DefaultRSocketRequester$DefaultRequestSpec.retrieveMono(DefaultRSocketRequester.java:290)
|_ ⇢ at org.springframework.messaging.rsocket.DefaultRSocketRequester$DefaultRequestSpec.retrieveMono(DefaultRSocketRequester.java:272)
|_ ⇢ at org.springframework.messaging.rsocket.DefaultRSocketRequester$DefaultRequestSpec.retrieveMono(DefaultRSocketRequester.java:272)
Stack trace:
at io.netty.handler.ssl.SslHandler.channelInactive(SslHandler.java:1063)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)
at io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:831)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:497)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:831)
Unfortunately, I can't tell you more at this point. It might be just some timing problem.
Cheers, Christoph
Comment From: wilkinsona
I've just seen some failures that appear to be similar:
NettyReactiveWebServerFactoryTests > basicSslFromFileSystem() FAILED
org.springframework.web.reactive.function.client.WebClientRequestException at ExchangeFunctions.java:141
Caused by: java.nio.channels.ClosedChannelException at SslHandler.java:1063
NettyReactiveWebServerFactoryTests > sslWantsClientAuthenticationSucceedsWithClientCertificate() FAILED
org.springframework.web.reactive.function.client.WebClientRequestException at ExchangeFunctions.java:141
Caused by: java.nio.channels.ClosedChannelException at SslHandler.java:1063
NettyReactiveWebServerFactoryTests > sslWantsClientAuthenticationSucceedsWithoutClientCertificate() FAILED
org.springframework.web.reactive.function.client.WebClientRequestException at ExchangeFunctions.java:141
Caused by: java.nio.channels.ClosedChannelException at SslHandler.java:1063
NettyReactiveWebServerFactoryTests > sslNeedsClientAuthenticationSucceedsWithClientCertificate() FAILED
org.springframework.web.reactive.function.client.WebClientRequestException at ExchangeFunctions.java:141
Caused by: java.nio.channels.ClosedChannelException at SslHandler.java:1063
NettyReactiveWebServerFactoryTests > basicSslFromClassPath() FAILED
org.springframework.web.reactive.function.client.WebClientRequestException at ExchangeFunctions.java:141
Caused by: java.nio.channels.ClosedChannelException at SslHandler.java:1063
I don't think I've seen these before. I suspect they're due to a change in Netty or Reactor Netty but I'm not sure which just yet. @violetagg, do you know of any changes in this area in the recent (Reactor) Netty releases?
Comment From: violetagg
@wilkinsona Please provide the full stack for the exception or a link to the logs from the failing tests.
Also in the original report there is org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactoryTests > sslWantsClientAuthenticationSucceedsWithoutClientCertificate()
is this also related to Reactor Netty/Netty?
Comment From: wilkinsona
More failures, with a build scan this time. In both cases, I was building with Java 11 (11.0.10+9
). Looking at the scan, the following looks rather suspicious:
java.lang.IncompatibleClassChangeError: Class io.netty.handler.ssl.ReferenceCountedOpenSslServerContext$OpenSslServerCertificateCallback does not implement the requested interface io.netty.internal.tcnative.CertificateCallback
at io.netty.internal.tcnative.CertificateCallbackTask.runTask(CertificateCallbackTask.java:40) ~[netty-tcnative-boringssl-static-2.0.39.Final.jar:na]
at io.netty.internal.tcnative.SSLTask.run(SSLTask.java:38) ~[netty-tcnative-boringssl-static-2.0.39.Final.jar:na]
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine$3.run(ReferenceCountedOpenSslEngine.java:1447) ~[netty-handler-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.ssl.SslHandler.runAllDelegatedTasks(SslHandler.java:1512) ~[netty-handler-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1526) ~[netty-handler-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1390) ~[netty-handler-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.ssl.SslHandler.decodeNonJdkCompatible(SslHandler.java:1245) ~[netty-handler-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1282) ~[netty-handler-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:507) ~[netty-codec-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:446) ~[netty-codec-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Comment From: wilkinsona
Thanks for taking a look so quickly, Violeta. Sorry, I didn't notice TomcatServletWebServerFactoryTests
at the end of the tests that failed for @dreis2211. They use Tomcat and Apache HTTP Client so this can't be (just) a (Reactor) Netty problem. There are some full stack traces in the build scan but I think we need to figure out the IncompatibleClassChangeError
before digging any further.
Comment From: violetagg
@wilkinsona This indicates a mismatch of the Netty binaries. Do you have other components (except Reactor Netty) that may have transitive dependencies to Netty or shadowing the Netty binaries? Also do you keep up-to-date also Netty tcnative module?
Comment From: dreis2211
The Tomcat one rarely fails in comparison to the Netty ones - I would say for 10 failures for Netty there is one for Tomcat.
Comment From: snicoll
I got the IncompatibleClassChangeError
and the fact that it is flaky is really surprising.
Comment From: wilkinsona
I don't understand it at all at the moment. OpenSslServerCertificateCallback
has implemented io.netty.internal.tcnative.CertificateCallback
since it was introduced 3 years ago and the callback interface's package hasn't changed in that time either. I'd also expect a failure when creating the CertificateCallbackTask
rather than when running it.
Mostly when run in the whole suite and not when run in isolation
I wonder if it's some sort of class loader problem such that CertificateCallbackTask
and OpenSslServerCertificateCallback
each reference a different io.netty.internal.tcnative.CertificateCallback
that was loaded by a different class loader. I'd still expect the call to the constuctor of CertificateCallbackTask
to fail in that case though.
Comment From: wilkinsona
It looks like a class loading and test ordering problem. I've reproduced the problem in the debugger and, in this case, CertificateCallbackTask
was loaded by org.springframework.boot.testsupport.classpath.ModifiedClassPathClassLoader@4647c5c6
while the callback was loaded by jdk.internal.loader.ClassLoaders$AppClassLoader@67424e82
. Looking at the path of the modified class path class loader, it appears to be from some Jetty 10 tests but the test that's failing is in NettyReactiveWebServerFactoryTests
.
Comment From: wilkinsona
JNI is in the mix too. Here's the stack when the CertificateCallbackTask
is created:
CertificateCallbackTask.<init>(long, byte[], byte[][], CertificateCallback) line: 29
SSL.readFromSSL(long, long, int) line: not available [native method] [local variables unavailable]
OpenSslEngine(ReferenceCountedOpenSslEngine).readPlaintextData(ByteBuffer) line: 635
OpenSslEngine(ReferenceCountedOpenSslEngine).unwrap(ByteBuffer[], int, int, ByteBuffer[], int, int) line: 1245
OpenSslEngine(ReferenceCountedOpenSslEngine).unwrap(ByteBuffer[], ByteBuffer[]) line: 1371
OpenSslEngine(ReferenceCountedOpenSslEngine).unwrap(ByteBuffer, ByteBuffer) line: 1414
SslHandler$SslEngineType$1.unwrap(SslHandler, ByteBuf, int, ByteBuf) line: 224
SslHandler.unwrap(ChannelHandlerContext, ByteBuf, int) line: 1338
SslHandler.decodeNonJdkCompatible(ChannelHandlerContext, ByteBuf) line: 1245
SslHandler.decode(ChannelHandlerContext, ByteBuf, List<Object>) line: 1282
SslHandler(ByteToMessageDecoder).decodeRemovalReentryProtection(ChannelHandlerContext, ByteBuf, List<Object>) line: 507
SslHandler(ByteToMessageDecoder).callDecode(ChannelHandlerContext, ByteBuf, List<Object>) line: 446
SslHandler(ByteToMessageDecoder).channelRead(ChannelHandlerContext, Object) line: 276
DefaultChannelHandlerContext(AbstractChannelHandlerContext).invokeChannelRead(Object) line: 379
AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object) line: 365
DefaultChannelPipeline$HeadContext(AbstractChannelHandlerContext).fireChannelRead(Object) line: 357
DefaultChannelPipeline$HeadContext.channelRead(ChannelHandlerContext, Object) line: 1410
DefaultChannelPipeline$HeadContext(AbstractChannelHandlerContext).invokeChannelRead(Object) line: 379
AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object) line: 365
DefaultChannelPipeline.fireChannelRead(Object) line: 919
NioSocketChannel$NioSocketChannelUnsafe(AbstractNioByteChannel$NioByteUnsafe).read() line: 166
NioEventLoop.processSelectedKey(SelectionKey, AbstractNioChannel) line: 719
NioEventLoop.processSelectedKeysOptimized() line: 655
NioEventLoop.processSelectedKeys() line: 581
NioEventLoop.run() line: 493
SingleThreadEventExecutor$4.run() line: 989
ThreadExecutorMap$2.run() line: 74
FastThreadLocalRunnable.run() line: 30
DefaultLoopResources$EventLoop(Thread).run() line: 834
The TCCL is the app class loader but CertificateCallbackTask
's class loader is a ModifiedClassPathClassLoader
from a previous test. It would appear that the native code beneath SSL.readFromSSL
is using the wrong class loader.
Comment From: dreis2211
Well, at least https://github.com/netty/netty-tcnative/commit/eb23bb10e08eb319c5452212fc9326572f5525f2 was done fairly recent
Comment From: wilkinsona
😀 I was just coming back here to comment with a link to https://github.com/netty/netty-tcnative/pull/642. If my analysis is right, I think netty/netty-tcnative@eb23bb1 will fix the Netty parts of this at least.
Until Netty tcNative 2.0.40 is released and we can upgrade, we may be able to work around the problem by changing the modified class path class loader to skip io.netty.internal.tcnative
classes.