Moving BrokerSubscriptionInfo processing into a new thread to prevent a
deadlock of the network bridge on startup
This commit is contained in:
Christopher L. Shannon (cshannon) 2016-10-24 07:51:34 -04:00
parent 1a811b72dd
commit b9cb02ae54
1 changed files with 51 additions and 23 deletions

View File

@ -163,6 +163,8 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
protected BrokerService brokerService = null; protected BrokerService brokerService = null;
private ObjectName mbeanObjectName; private ObjectName mbeanObjectName;
private final ExecutorService serialExecutor = Executors.newSingleThreadExecutor(); private final ExecutorService serialExecutor = Executors.newSingleThreadExecutor();
//Use a new executor for processing BrokerSubscriptionInfo so we don't block other threads
private final ExecutorService syncExecutor = Executors.newSingleThreadExecutor();
private Transport duplexInboundLocalBroker = null; private Transport duplexInboundLocalBroker = null;
private ProducerInfo duplexInboundLocalProducerInfo; private ProducerInfo duplexInboundLocalProducerInfo;
@ -295,6 +297,14 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
List<Runnable> pendingTasks = serialExecutor.shutdownNow(); List<Runnable> pendingTasks = serialExecutor.shutdownNow();
LOG.info("pending tasks on stop {}", pendingTasks); LOG.info("pending tasks on stop {}", pendingTasks);
} }
//Shutdown the syncExecutor, call countDown to make sure a thread can
//terminate if it is waiting
staticDestinationsLatch.countDown();
syncExecutor.shutdown();
if (!syncExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
List<Runnable> pendingTasks = syncExecutor.shutdownNow();
LOG.info("pending tasks on stop {}", pendingTasks);
}
localBroker.oneway(new ShutdownInfo()); localBroker.oneway(new ShutdownInfo());
remoteBroker.oneway(new ShutdownInfo()); remoteBroker.oneway(new ShutdownInfo());
} catch (Throwable e) { } catch (Throwable e) {
@ -648,10 +658,20 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
} else if (command.isBrokerInfo()) { } else if (command.isBrokerInfo()) {
futureRemoteBrokerInfo.set((BrokerInfo) command); futureRemoteBrokerInfo.set((BrokerInfo) command);
} else if (command instanceof BrokerSubscriptionInfo) { } else if (command instanceof BrokerSubscriptionInfo) {
final BrokerSubscriptionInfo brokerSubscriptionInfo = (BrokerSubscriptionInfo) command;
//Start in a new thread so we don't block the transport waiting for staticDestinations
syncExecutor.execute(new Runnable() {
@Override
public void run() {
try {
staticDestinationsLatch.await(); staticDestinationsLatch.await();
BrokerSubscriptionInfo subInfo = (BrokerSubscriptionInfo) command; //Make sure after the countDown of staticDestinationsLatch we aren't stopping
if (!disposed.get()) {
BrokerSubscriptionInfo subInfo = brokerSubscriptionInfo;
LOG.debug("Received Remote BrokerSubscriptionInfo on {} from {}", LOG.debug("Received Remote BrokerSubscriptionInfo on {} from {}",
this.brokerService.getBrokerName(), subInfo.getBrokerName()); brokerService.getBrokerName(), subInfo.getBrokerName());
if (configuration.isSyncDurableSubs() && configuration.isConduitSubscriptions() if (configuration.isSyncDurableSubs() && configuration.isConduitSubscriptions()
&& !configuration.isDynamicOnly()) { && !configuration.isDynamicOnly()) {
@ -676,6 +696,14 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
} }
} }
} }
}
} catch (Exception e) {
LOG.warn("Error processing BrokerSubscriptionInfo: {}", e.getMessage(), e);
LOG.debug(e.getMessage(), e);
}
}
});
} else if (command.getClass() == ConnectionError.class) { } else if (command.getClass() == ConnectionError.class) {
ConnectionError ce = (ConnectionError) command; ConnectionError ce = (ConnectionError) command;
serviceRemoteException(ce.getException()); serviceRemoteException(ce.getException());