Skip to content

Commit c722ab7

Browse files
committed
test(log): pin TronLogShutdownHook wait-window semantics
1 parent cb6db14 commit c722ab7

2 files changed

Lines changed: 89 additions & 1 deletion

File tree

framework/src/main/java/org/tron/core/config/TronLogShutdownHook.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ public class TronLogShutdownHook extends ShutdownHookBase {
2121
* shutdownNow + 60 s await). 180 s is therefore not a hard upper bound, but
2222
* a pragmatic headroom that assumes the many pools in the node shut down
2323
* largely in parallel; in pathological cases trailing shutdown logs may
24-
* still be truncated.
24+
* still be truncated. In practice 180 s of shutdown output is also enough
25+
* to diagnose most stalls — if a pool is still alive past that window the
26+
* earlier logs already carry the stack/trace context needed to locate the
27+
* offender, so truncating the tail is an acceptable trade-off against
28+
* holding JVM exit open indefinitely.
2529
*/
2630
private static final long MAX_WAIT_MS = 3 * 60 * 1000;
2731

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package org.tron.core.config;
2+
3+
import static org.junit.Assert.assertFalse;
4+
import static org.junit.Assert.assertTrue;
5+
6+
import java.util.concurrent.TimeUnit;
7+
import java.util.concurrent.atomic.AtomicBoolean;
8+
import org.junit.After;
9+
import org.junit.Before;
10+
import org.junit.Test;
11+
12+
public class TronLogShutdownHookTest {
13+
14+
private boolean originalShutDown;
15+
16+
@Before
17+
public void saveShutDownFlag() {
18+
originalShutDown = TronLogShutdownHook.shutDown;
19+
}
20+
21+
@After
22+
public void restoreShutDownFlag() {
23+
TronLogShutdownHook.shutDown = originalShutDown;
24+
}
25+
26+
@Test(timeout = 5_000)
27+
public void returnsImmediatelyWhenAlreadyShutDown() {
28+
TronLogShutdownHook.shutDown = true;
29+
30+
TronLogShutdownHook hook = new TronLogShutdownHook();
31+
long startNs = System.nanoTime();
32+
hook.run();
33+
long elapsedMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
34+
assertTrue("hook should exit fast when shutDown==true, elapsed=" + elapsedMs + "ms",
35+
elapsedMs < 2_000);
36+
}
37+
38+
@Test(timeout = 10_000)
39+
public void wakesUpWhenShutDownFlagFlips() throws InterruptedException {
40+
TronLogShutdownHook.shutDown = false;
41+
42+
TronLogShutdownHook hook = new TronLogShutdownHook();
43+
Thread runner = new Thread(hook, "shutdown-hook-test-runner");
44+
runner.setDaemon(true);
45+
runner.start();
46+
47+
Thread.sleep(300);
48+
long flipNs = System.nanoTime();
49+
TronLogShutdownHook.shutDown = true;
50+
51+
runner.join(5_000);
52+
long elapsedAfterFlipMs =
53+
TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - flipNs);
54+
55+
assertFalse("runner should have exited after flag flipped, still alive",
56+
runner.isAlive());
57+
// The loop sleeps in 100 ms slices, so it should wake up well inside one
58+
// slice's worth of jitter. 1 s is comfortable even on slow CI.
59+
assertTrue("hook should return shortly after flag flip, elapsed="
60+
+ elapsedAfterFlipMs + "ms", elapsedAfterFlipMs < 1_000);
61+
}
62+
63+
@Test(timeout = 10_000)
64+
public void preservesInterruptStatusWhenInterrupted() throws InterruptedException {
65+
TronLogShutdownHook.shutDown = false;
66+
67+
TronLogShutdownHook hook = new TronLogShutdownHook();
68+
AtomicBoolean interruptedAfterRun = new AtomicBoolean(false);
69+
Thread runner = new Thread(() -> {
70+
hook.run();
71+
interruptedAfterRun.set(Thread.currentThread().isInterrupted());
72+
}, "shutdown-hook-test-interrupt");
73+
runner.setDaemon(true);
74+
runner.start();
75+
76+
Thread.sleep(200);
77+
runner.interrupt();
78+
79+
runner.join(5_000);
80+
assertFalse("runner should have exited after interrupt", runner.isAlive());
81+
assertTrue("run() must re-assert interrupt status after catching "
82+
+ "InterruptedException", interruptedAfterRun.get());
83+
}
84+
}

0 commit comments

Comments
 (0)