Synchronize access to shared http server map (#3117)

* Synchronize access to shared http server map

Fixes #2565

Signed-off-by: Thomas Segismont <tsegismont@gmail.com>

* Synchronize access to shared net server map too

Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
This commit is contained in:
Thomas Segismont
2019-09-26 14:55:11 +02:00
committed by GitHub
parent 017abb9352
commit 99901a095a
2 changed files with 19 additions and 10 deletions

View File

@@ -12,7 +12,8 @@
package io.vertx.core.http.impl;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.ChannelGroupFuture;
import io.netty.channel.group.DefaultChannelGroup;
@@ -226,10 +227,11 @@ public class HttpServerImpl implements HttpServer, Closeable, MetricsProvider {
applicationProtocols = applicationProtocols.stream().filter(v -> v != HttpVersion.HTTP_2).collect(Collectors.toList());
}
sslHelper.setApplicationProtocols(applicationProtocols);
synchronized (vertx.sharedHttpServers()) {
Map<ServerID, HttpServerImpl> sharedHttpServers = vertx.sharedHttpServers();
synchronized (sharedHttpServers) {
this.actualPort = port; // Will be updated on bind for a wildcard port
id = new ServerID(port, host);
HttpServerImpl shared = vertx.sharedHttpServers().get(id);
HttpServerImpl shared = sharedHttpServers.get(id);
if (shared == null || port == 0) {
serverChannelGroup = new DefaultChannelGroup("vertx-acceptor-channels", GlobalEventExecutor.INSTANCE);
ServerBootstrap bootstrap = new ServerBootstrap();
@@ -243,7 +245,9 @@ public class HttpServerImpl implements HttpServer, Closeable, MetricsProvider {
bindFuture = AsyncResolveConnectHelper.doBind(vertx, address, bootstrap);
bindFuture.addListener(res -> {
if (res.failed()) {
vertx.sharedHttpServers().remove(id);
synchronized (sharedHttpServers) {
sharedHttpServers.remove(id);
}
} else {
Channel serverChannel = res.result();
if (serverChannel.localAddress() instanceof InetSocketAddress) {
@@ -265,7 +269,7 @@ public class HttpServerImpl implements HttpServer, Closeable, MetricsProvider {
listening = false;
return this;
}
vertx.sharedHttpServers().put(id, this);
sharedHttpServers.put(id, this);
actualServer = this;
} else {
// Server already exists with that host/port - we will use that

View File

@@ -167,11 +167,12 @@ public class NetServerImpl implements Closeable, MetricsProvider, NetServer {
listenContext = vertx.getOrCreateContext();
registeredHandler = handler;
synchronized (vertx.sharedNetServers()) {
Map<ServerID, NetServerImpl> sharedNetServers = vertx.sharedNetServers();
synchronized (sharedNetServers) {
this.actualPort = socketAddress.port(); // Will be updated on bind for a wildcard port
String hostOrPath = socketAddress.host() != null ? socketAddress.host() : socketAddress.path();
id = new ServerID(actualPort, hostOrPath);
NetServerImpl shared = vertx.sharedNetServers().get(id);
NetServerImpl shared = sharedNetServers.get(id);
if (shared == null || actualPort == 0) { // Wildcard port will imply a new actual server each time
serverChannelGroup = new DefaultChannelGroup("vertx-acceptor-channels", GlobalEventExecutor.INSTANCE);
@@ -234,13 +235,17 @@ public class NetServerImpl implements Closeable, MetricsProvider, NetServer {
}
NetServerImpl.this.id = new ServerID(NetServerImpl.this.actualPort, id.host);
serverChannelGroup.add(ch);
vertx.sharedNetServers().put(id, NetServerImpl.this);
synchronized (sharedNetServers) {
sharedNetServers.put(id, NetServerImpl.this);
}
VertxMetrics metrics = vertx.metricsSPI();
if (metrics != null) {
this.metrics = metrics.createNetServerMetrics(options, new SocketAddressImpl(id.port, id.host));
}
} else {
vertx.sharedNetServers().remove(id);
synchronized (sharedNetServers) {
sharedNetServers.remove(id);
}
}
});
@@ -256,7 +261,7 @@ public class NetServerImpl implements Closeable, MetricsProvider, NetServer {
return;
}
if (actualPort != 0) {
vertx.sharedNetServers().put(id, this);
sharedNetServers.put(id, this);
}
actualServer = this;
} else {