This is an automated email from the ASF dual-hosted git repository.

alexpl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 3f312812b03 IGNITE-27879 Add parent process listener to 
IgniteCompatibilityNodeRunner (#12756)
3f312812b03 is described below

commit 3f312812b03b8163aafd5617a24fcf846ca75f55
Author: Aleksandr Chesnokov <[email protected]>
AuthorDate: Thu Feb 19 12:28:25 2026 +0300

    IGNITE-27879 Add parent process listener to IgniteCompatibilityNodeRunner 
(#12756)
---
 .../junits/IgniteCompatibilityNodeRunner.java      | 45 +++++++++++++++++++---
 1 file changed, 40 insertions(+), 5 deletions(-)

diff --git 
a/modules/compatibility/src/test/java/org/apache/ignite/compatibility/testframework/junits/IgniteCompatibilityNodeRunner.java
 
b/modules/compatibility/src/test/java/org/apache/ignite/compatibility/testframework/junits/IgniteCompatibilityNodeRunner.java
index 297ec12b7de..0a83943e4af 100644
--- 
a/modules/compatibility/src/test/java/org/apache/ignite/compatibility/testframework/junits/IgniteCompatibilityNodeRunner.java
+++ 
b/modules/compatibility/src/test/java/org/apache/ignite/compatibility/testframework/junits/IgniteCompatibilityNodeRunner.java
@@ -37,7 +37,6 @@ import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteInClosure;
 import org.apache.ignite.lang.IgniteProductVersion;
-import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.multijvm.IgniteNodeRunner;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -79,6 +78,8 @@ public class IgniteCompatibilityNodeRunner extends 
IgniteNodeRunner {
                     " [optional/path/to/closure/file]");
             }
 
+            startParentPipeWatcher();
+
             final Thread watchdog = delayedDumpClasspath();
 
             IgniteConfiguration cfg = 
CompatibilityTestsFacade.getConfiguration();
@@ -96,16 +97,13 @@ public class IgniteCompatibilityNodeRunner extends 
IgniteNodeRunner {
             cfg.setIgniteInstanceName(args[1]);
             cfg.setNodeId(nodeId);
 
-            final Ignite ignite = Ignition.start(cfg);
+            ignite = Ignition.start(cfg);
 
             assert ignite.cluster().node(syncNodeId) != null : "Node has not 
joined [id=" + nodeId + "]";
 
             assert 
ignite.cluster().localNode().version().compareToIgnoreTimestamp(expNodeVer) == 
0 : "Node is of unexpected " +
                 "version: [act=" + ignite.cluster().localNode().version() + ", 
exp=" + expNodeVer + ']';
 
-            // It needs to set private static field 'ignite' of the 
IgniteNodeRunner class via reflection
-            GridTestUtils.setFieldValue(new IgniteNodeRunner(), "ignite", 
ignite);
-
             if (args.length == 6) {
                 IgniteInClosure<Ignite> clo = 
readClosureFromFileAndDelete(args[5]);
 
@@ -127,6 +125,43 @@ public class IgniteCompatibilityNodeRunner extends 
IgniteNodeRunner {
         }
     }
 
+    /**
+     * Checks that parent process is alive.
+     *
+     * <p>We listen on {@code System.in} because this compatibility node is 
started by the parent JVM via
+     * {@link ProcessBuilder}, where {@code System.in} is a pipe from the 
parent. When the parent process exits,
+     * the write-end of the pipe is closed and {@code System.in.read()} 
returns EOF. We treat this as a signal
+     * to stop Ignite and terminate the process.</p>
+     */
+    private static void startParentPipeWatcher() {
+        Thread thread = new Thread(() -> {
+            try {
+                while (System.in.read() != -1) {
+                    // No-op
+                }
+            }
+            catch (IOException e) {
+                X.println("Failed to read parent stdin pipe, stopping 
compatibility node: " + e);
+            }
+
+            X.println("Parent JVM stdin pipe is closed, stopping compatibility 
node");
+
+            try {
+                if (ignite != null)
+                    Ignition.stop(ignite.name(), true);
+            }
+            catch (Throwable e) {
+                X.println("Failed to stop compatibility node after parent pipe 
closure: " + e);
+            }
+            finally {
+                System.exit(0);
+            }
+        }, "compatibility-parent-pipe-watcher");
+
+        thread.setDaemon(true);
+        thread.start();
+    }
+
     /**
      * Starts background watchdog thread which will dump main thread 
stacktrace and classpath dump if main thread
      * will not respond with node startup finished.

Reply via email to