Skip to content

Commit 9b75259

Browse files
Fixing github issue 524
1 parent ee88f45 commit 9b75259

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,7 @@ public void shutdown() {
234234
}
235235

236236
/**
237-
* Wait for the looper to complete processing all messages before proceeding with shutdown. This
238-
* prevents the race condition where the network executor is shut down before the looper finishes
237+
* Wait for the looper to complete processing all messages before proceedin with shutdown. This prevents the race condition where the network executor is shut down before the looper finishes
239238
* submitting all batches.
240239
*/
241240
private void waitForLooperCompletion() {
@@ -257,18 +256,38 @@ private void waitForLooperCompletion() {
257256
}
258257

259258
public void shutdownAndWait(ExecutorService executor, String name) {
259+
boolean isLooperExecutor = name != null && name.equalsIgnoreCase("looper");
260260
try {
261261
executor.shutdown();
262-
final boolean executorTerminated = executor.awaitTermination(1, TimeUnit.SECONDS);
263-
264-
log.print(
265-
VERBOSE,
266-
"%s executor %s.",
267-
name,
268-
executorTerminated ? "terminated normally" : "timed out");
262+
boolean terminated = executor.awaitTermination(1, TimeUnit.MILLISECONDS);
263+
if (terminated) {
264+
log.print(VERBOSE, "%s executor terminated normally.", name);
265+
return;
266+
}
267+
if (isLooperExecutor) {
268+
// not terminated within timeout -> force shutdown
269+
log.print(VERBOSE, "%s did not terminate in %d ms; requesting shutdownNow().", name, 1);
270+
List<Runnable> dropped = executor.shutdownNow(); // interrupts running tasks
271+
log.print(VERBOSE, "%s shutdownNow returned %d queued tasks that never started.", name, dropped.size());
272+
273+
// optional short wait to give interrupted tasks a chance to exit
274+
boolean terminatedAfterForce = executor.awaitTermination(1, TimeUnit.MILLISECONDS);
275+
log.print(VERBOSE, "%s executor %s after shutdownNow().", name,
276+
terminatedAfterForce ? "terminated" : "still running (did not terminate)");
277+
278+
if (!terminatedAfterForce) {
279+
// final warning — investigate tasks that ignore interrupts
280+
log.print(ERROR, "%s executor still did not terminate; tasks may be ignoring interrupts.", name);
281+
}
282+
}
269283
} catch (InterruptedException e) {
284+
// Preserve interrupt status and attempt forceful shutdown
270285
log.print(ERROR, e, "Interrupted while stopping %s executor.", name);
271286
Thread.currentThread().interrupt();
287+
if (isLooperExecutor) {
288+
List<Runnable> dropped = executor.shutdownNow();
289+
log.print(VERBOSE, "%s shutdownNow invoked after interrupt; %d tasks returned.", name, dropped.size());
290+
}
272291
}
273292
}
274293

@@ -522,4 +541,4 @@ private static int getBatchDefaultSize(int contextSize, int currentMessageNumber
522541
+ String.valueOf(Integer.MAX_VALUE).length();
523542
}
524543
}
525-
}
544+
}

0 commit comments

Comments
 (0)