Skip to content

Commit d2acf96

Browse files
authored
IGNITE-27929 Add parent process listener to IgniteNodeRunner (#12933)
1 parent 918de0d commit d2acf96

2 files changed

Lines changed: 43 additions & 0 deletions

File tree

modules/compatibility/src/test/java/org/apache/ignite/compatibility/testframework/junits/IgniteCompatibilityNodeRunner.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ public static void main(String[] args) throws Exception {
128128
/**
129129
* Checks that parent process is alive.
130130
*
131+
* <p>This logic is intentionally duplicated here and in {@link IgniteNodeRunner}.
132+
* Compatibility tests may run with an older {@code ignite-core-tests} on the classpath,
133+
* so this runner cannot safely depend on newly added methods in {@code IgniteNodeRunner}.</p>
134+
*
131135
* <p>We listen on {@code System.in} because this compatibility node is started by the parent JVM via
132136
* {@link ProcessBuilder}, where {@code System.in} is a pipe from the parent. When the parent process exits,
133137
* the write-end of the pipe is closed and {@code System.in.read()} returns EOF. We treat this as a signal

modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteNodeRunner.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,50 @@ public static void main(String[] args) throws Exception {
6767

6868
X.println("Starting Ignite Node... Args=" + Arrays.toString(args));
6969

70+
startParentPipeWatcher();
71+
7072
IgniteConfiguration cfg = readCfgFromFileAndDeleteFile(args[0]);
7173

7274
ignite = Ignition.start(cfg);
7375
}
7476

77+
/**
78+
* Checks that parent process is alive.
79+
*
80+
* <p>We listen on {@code System.in} because this node runner is started by the parent JVM via
81+
* {@link ProcessBuilder}, where {@code System.in} is a pipe from the parent. When the parent process exits,
82+
* the write-end of the pipe is closed and {@code System.in.read()} returns EOF. We treat this as a signal
83+
* to stop Ignite and terminate the process.</p>
84+
*/
85+
private static void startParentPipeWatcher() {
86+
Thread thread = new Thread(() -> {
87+
try {
88+
while (System.in.read() != -1) {
89+
// No-op
90+
}
91+
}
92+
catch (IOException e) {
93+
X.println("Failed to read parent stdin pipe, stopping Ignite node: " + e);
94+
}
95+
96+
X.println("Parent JVM stdin pipe is closed, stopping Ignite node");
97+
98+
try {
99+
if (ignite != null)
100+
Ignition.stop(ignite.name(), true);
101+
}
102+
catch (Throwable e) {
103+
X.println("Failed to stop Ignite node after parent pipe closure: " + e);
104+
}
105+
finally {
106+
System.exit(0);
107+
}
108+
}, "ignite-parent-pipe-watcher");
109+
110+
thread.setDaemon(true);
111+
thread.start();
112+
}
113+
75114
/**
76115
* @return Ignite instance started at main.
77116
*/

0 commit comments

Comments
 (0)