Don't throw NettyWebServer on permission errors

Update `NettyWebServer` so that the `PortInUseException` is not thrown
for permission denied errors.

Fixes gh-19807
pull/22089/head
Phillip Webb 5 years ago
parent c7611112f7
commit a2fdf23e41

@ -18,6 +18,7 @@ package org.springframework.boot.web.embedded.netty;
import java.time.Duration; import java.time.Duration;
import io.netty.channel.unix.Errors.NativeIoException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import reactor.netty.ChannelBindException; import reactor.netty.ChannelBindException;
@ -42,6 +43,11 @@ import org.springframework.util.Assert;
*/ */
public class NettyWebServer implements WebServer { public class NettyWebServer implements WebServer {
/**
* Permission denied error code from {@code errno.h}.
*/
private static final int ERROR_NO_EACCES = -13;
private static final Log logger = LogFactory.getLog(NettyWebServer.class); private static final Log logger = LogFactory.getLog(NettyWebServer.class);
private final HttpServer httpServer; private final HttpServer httpServer;
@ -68,7 +74,7 @@ public class NettyWebServer implements WebServer {
} }
catch (Exception ex) { catch (Exception ex) {
ChannelBindException bindException = findBindException(ex); ChannelBindException bindException = findBindException(ex);
if (bindException != null) { if (bindException != null && !isPermissionDenied(bindException.getCause())) {
throw new PortInUseException(bindException.localPort(), ex); throw new PortInUseException(bindException.localPort(), ex);
} }
throw new WebServerException("Unable to start Netty", ex); throw new WebServerException("Unable to start Netty", ex);
@ -78,6 +84,17 @@ public class NettyWebServer implements WebServer {
} }
} }
private boolean isPermissionDenied(Throwable bindExceptionCause) {
try {
if (bindExceptionCause instanceof NativeIoException) {
return ((NativeIoException) bindExceptionCause).expectedErr() == ERROR_NO_EACCES;
}
}
catch (Throwable ex) {
}
return false;
}
private DisposableServer startHttpServer() { private DisposableServer startHttpServer() {
if (this.lifecycleTimeout != null) { if (this.lifecycleTimeout != null) {
return this.httpServer.handle(this.handlerAdapter).bindNow(this.lifecycleTimeout); return this.httpServer.handle(this.handlerAdapter).bindNow(this.lifecycleTimeout);

Loading…
Cancel
Save