epoll/kqueue transport bind exception detection does not work on linux with LANGUAGE != en
See original GitHub issueWhen trying to start a server with a port that is already bind on a epoll/kqueue transport based linux system with LANGUAGE
not set to en
a io.netty.channel.unix.Errors$NativeIoException
instead of a ChannelBindException
is thrown.
This leads to failed test cases when trying to build reactor-netty
UdpServerTests > portBindingException() FAILED
reactor.core.Exceptions$ReactiveException: io.netty.channel.unix.Errors$NativeIoException: bind(..) failed: Die Adresse wird bereits verwendet
at reactor.core.Exceptions.propagate(Exceptions.java:392)
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:137)
at reactor.core.publisher.Mono.block(Mono.java:1727)
at reactor.netty.udp.UdpServer.bindNow(UdpServer.java:120)
at reactor.netty.udp.UdpServerTests.portBindingException(UdpServerTests.java:266)
Caused by:
io.netty.channel.unix.Errors$NativeIoException: bind(..) failed: Die Adresse wird bereits verwendet
264 tests completed, 4 failed, 3 skipped
Expected Behavior
ChannelBindException
for e.g. test case UdpServerTests.portBindingException
Actual Behavior
io.netty.channel.unix.Errors$NativeIoException
is handled by reactor-netty
and wrapped in ChannelBindException
Steps to Reproduce
Execute UdpServerTests.portBindingException on an epoll/kqueue based linux
Possible Solution
Root problem seems to be the current solution which tries to detect and wrap such exception based on the message string provided by the underlying OS.
The string check Address already in use
will fail on linux environments with a different language. When setting the language to german the message provided by the OS is Die Adresse wird bereits verwendet
Maybe the check can be based on the cannonical name of the class instead
/**
* Check if {@code t} is a {@link BindException}
*
* @param t {@code Throwable} to check
* @return true if {@code t} is a {@link BindException}
*/
private boolean isBindException(Throwable t) {
if (t instanceof BindException) {
return true;
}
// With epoll/kqueue transport it is
// io.netty.channel.unix.Errors$NativeIoException: bind(..) failed: Address already in use
else if (t instanceof IOException && t.getClass().getCanonicalName().equals("io.netty.channel.unix.Errors.NativeIoException")) {
return true;
}
return false;
}
@Override
public void onError(Throwable t) {
if (bindAddress != null && isBindException(t)) {
sink.error(ChannelBindException.fail(bindAddress.get(), null));
}
else {
sink.error(t);
}
}
Your Environment
Reactor version(s) used: reactor-netty 1.0.7 JVM version : OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.7+10, mixed mode) OS and version: Linux 5.12.10-arch1-1 #1 SMP PREEMPT Thu, 10 Jun 2021 16:34:50 +0000 x86_64 GNU/Linux
Issue Analytics
- State:
- Created 2 years ago
- Comments:5 (5 by maintainers)
You’re right. I will submit a push request
It should be this one
https://github.com/netty/netty/blob/0d5774a82b470833c5f8a84fa4708142a4801f52/transport-native-unix-common/src/main/java/io/netty/channel/unix/Errors.java#L84
so most probably it will be OK wdyt?