Skip to content

Commit 054f5ee

Browse files
sometimes fork the thread
1 parent f7b7faf commit 054f5ee

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

server/src/main/java/org/elasticsearch/indices/cluster/IndicesClusterStateService.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ protected void doClose() {}
246246
* other lenience to handle that. It'd be better to wait for the shard locks to be released and then delete the data. See #74149.
247247
*/
248248
private volatile SubscribableListener<Void> lastClusterStateShardsClosedListener = SubscribableListener.nullSuccess();
249+
private int shardsClosedListenerChainLength = 0;
249250

250251
@Nullable // if not currently applying a cluster state
251252
private RefCountingListener currentClusterStateShardsClosedListeners;
@@ -274,8 +275,26 @@ public synchronized void applyClusterState(final ClusterChangedEvent event) {
274275
lastClusterStateShardsClosedListener = new SubscribableListener<>();
275276
currentClusterStateShardsClosedListeners = new RefCountingListener(lastClusterStateShardsClosedListener);
276277
try {
277-
previousShardsClosedListener.addListener(currentClusterStateShardsClosedListeners.acquire());
278278
doApplyClusterState(event);
279+
// HACK: chain listeners but avoid too deep of a stack
280+
{
281+
if (previousShardsClosedListener.isDone()) {
282+
shardsClosedListenerChainLength = 0;
283+
}
284+
previousShardsClosedListener.addListener(
285+
currentClusterStateShardsClosedListeners.acquire(),
286+
// Sometimes fork the listener on a different thread.
287+
// Chaining too many listeners might trigger a stackoverflow exception on the thread that eventually gets to
288+
// execute them all (because the last thread that decreases the ref count to 0 of a {@link RefCountingListener}
289+
// also executes its listeners, which in turn might decrease the ref count to 0 of another
290+
// {@link RefCountingListerner}, again executing its listeners, etc...).
291+
shardsClosedListenerChainLength++ < 10 ? EsExecutors.DIRECT_EXECUTOR_SERVICE : threadPool.generic(),
292+
null
293+
);
294+
if (shardsClosedListenerChainLength >= 10) {
295+
shardsClosedListenerChainLength = 0;
296+
}
297+
}
279298
} finally {
280299
currentClusterStateShardsClosedListeners.close();
281300
currentClusterStateShardsClosedListeners = null;

0 commit comments

Comments
 (0)