Skip to content

Commit ee9b32e

Browse files
committed
Avoid forking in AbstractSearchAsyncAction (#71580)
We don't need to fork when handling unassigned shard failures in AbstractSearchAsyncAction as we never call it recursively. Relates #70792
1 parent f178e33 commit ee9b32e

File tree

1 file changed

+28
-1
lines changed

1 file changed

+28
-1
lines changed

server/src/main/java/org/elasticsearch/action/search/AbstractSearchAsyncAction.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,32 @@ private boolean checkMinimumVersion(GroupShardsIterator<SearchShardIterator> sha
251251
return true;
252252
}
253253

254+
private boolean assertExecuteOnStartThread() {
255+
// Ensure that the current code has the following stacktrace:
256+
// AbstractSearchAsyncAction#start -> AbstractSearchAsyncAction#executePhase -> AbstractSearchAsyncAction#performPhaseOnShard
257+
final StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
258+
assert stackTraceElements.length >= 6 : stackTraceElements;
259+
int index = 0;
260+
assert stackTraceElements[index++].getMethodName().equals("getStackTrace");
261+
assert stackTraceElements[index++].getMethodName().equals("assertExecuteOnStartThread");
262+
assert stackTraceElements[index++].getMethodName().equals("performPhaseOnShard");
263+
if (stackTraceElements[index].getMethodName().equals("performPhaseOnShard")) {
264+
assert stackTraceElements[index].getClassName().endsWith("CanMatchPreFilterSearchPhase");
265+
index++;
266+
}
267+
assert stackTraceElements[index].getClassName().endsWith("AbstractSearchAsyncAction");
268+
assert stackTraceElements[index++].getMethodName().equals("run");
269+
270+
assert stackTraceElements[index].getClassName().endsWith("AbstractSearchAsyncAction");
271+
assert stackTraceElements[index++].getMethodName().equals("executePhase");
272+
273+
assert stackTraceElements[index].getClassName().endsWith("AbstractSearchAsyncAction");
274+
assert stackTraceElements[index++].getMethodName().equals("start");
275+
276+
assert stackTraceElements[index].getClassName().endsWith("AbstractSearchAsyncAction") == false;
277+
return true;
278+
}
279+
254280
protected void performPhaseOnShard(final int shardIndex, final SearchShardIterator shardIt, final SearchShardTarget shard) {
255281
/*
256282
* We capture the thread that this phase is starting on. When we are called back after executing the phase, we are either on the
@@ -260,9 +286,10 @@ protected void performPhaseOnShard(final int shardIndex, final SearchShardIterat
260286
* we can continue (cf. InitialSearchPhase#maybeFork).
261287
*/
262288
if (shard == null) {
289+
assert assertExecuteOnStartThread();
263290
SearchShardTarget unassignedShard = new SearchShardTarget(null, shardIt.shardId(),
264291
shardIt.getClusterAlias(), shardIt.getOriginalIndices());
265-
fork(() -> onShardFailure(shardIndex, unassignedShard, shardIt, new NoShardAvailableActionException(shardIt.shardId())));
292+
onShardFailure(shardIndex, unassignedShard, shardIt, new NoShardAvailableActionException(shardIt.shardId()));
266293
} else {
267294
final PendingExecutions pendingExecutions = throttleConcurrentRequests ?
268295
pendingExecutionsPerNode.computeIfAbsent(shard.getNodeId(), n -> new PendingExecutions(maxConcurrentRequestsPerNode))

0 commit comments

Comments
 (0)