You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2022/02/03 16:01:51 UTC

[maven-surefire] 01/01: [SUREFIRE-1999] PPID checker should redirect the error stream of the checker command to a dump file

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

tibordigana pushed a commit to branch InterruptedIOException
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git

commit 3af614dc02630d1bba9ee86aec717535ac6ac359
Author: Tibor Digaňa <ti...@apache.org>
AuthorDate: Thu Feb 3 06:20:07 2022 +0100

    [SUREFIRE-1999] PPID checker should redirect the error stream of the checker command to a dump file
---
 .../apache/maven/surefire/booter/PpidChecker.java  | 27 ++++++++-
 .../maven/surefire/booter/PpidCheckerTest.java     | 67 ++++++++++++++++++++++
 2 files changed, 92 insertions(+), 2 deletions(-)

diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java
index a5287c7..3eb703d 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java
@@ -25,6 +25,7 @@ import javax.annotation.Nonnull;
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.Charset;
+import java.nio.file.Path;
 import java.text.SimpleDateFormat;
 import java.util.Queue;
 import java.util.Scanner;
@@ -36,6 +37,9 @@ import java.util.regex.Pattern;
 import static java.lang.Integer.parseInt;
 import static java.lang.Long.parseLong;
 import static java.lang.String.join;
+import static java.nio.file.Files.createTempFile;
+import static java.nio.file.Files.delete;
+import static java.nio.file.Files.readAllBytes;
 import static java.util.concurrent.TimeUnit.DAYS;
 import static java.util.concurrent.TimeUnit.HOURS;
 import static java.util.concurrent.TimeUnit.MINUTES;
@@ -394,14 +398,16 @@ final class PpidChecker
         ProcessInfo execute( String... command )
         {
             ProcessBuilder processBuilder = new ProcessBuilder( command );
-            processBuilder.redirectErrorStream( true );
             Process process = null;
             ProcessInfo processInfo = INVALID_PROCESS_INFO;
             StringBuilder out = new StringBuilder( 64 );
             out.append( join( " ", command ) )
                 .append( NL );
+            Path stdErr = null;
             try
             {
+                stdErr = createTempFile( "surefire", null );
+                processBuilder.redirectError( stdErr.toFile() );
                 if ( IS_OS_HP_UX ) // force to run shell commands in UNIX Standard mode on HP-UX
                 {
                     processBuilder.environment().put( "UNIX95", "1" );
@@ -447,11 +453,28 @@ final class PpidChecker
                 if ( process != null )
                 {
                     destroyableCommands.remove( process );
-                    process.destroy();
                     closeQuietly( process.getInputStream() );
                     closeQuietly( process.getErrorStream() );
                     closeQuietly( process.getOutputStream() );
                 }
+
+                if ( stdErr != null )
+                {
+                    try
+                    {
+                        String error = new String( readAllBytes( stdErr ) ).trim();
+                        if ( !error.isEmpty() )
+                        {
+                            DumpErrorSingleton.getSingleton()
+                                .dumpText( error );
+                        }
+                        delete( stdErr );
+                    }
+                    catch ( IOException e )
+                    {
+                        // cannot do anything about it, the dump file writes would fail as well
+                    }
+                }
             }
         }
     }
diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java
index 5f7a744..5455146 100644
--- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java
+++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java
@@ -19,6 +19,8 @@ package org.apache.maven.surefire.booter;
  * under the License.
  */
 
+import org.apache.maven.surefire.api.booter.DumpErrorSingleton;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -27,7 +29,9 @@ import java.io.File;
 import java.lang.management.ManagementFactory;
 import java.util.regex.Matcher;
 
+import static java.nio.file.Files.readAllBytes;
 import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.maven.surefire.shared.io.FileUtils.getTempDirectory;
 import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_UNIX;
 import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_WINDOWS;
 import static org.apache.maven.surefire.booter.ProcessInfo.unixProcessInfo;
@@ -54,6 +58,15 @@ public class PpidCheckerTest
     @Rule
     public final ExpectedException exceptions = ExpectedException.none();
 
+    @Before
+    public void deinit()
+    {
+        DumpErrorSingleton dumper = DumpErrorSingleton.getSingleton();
+        setInternalState( dumper, "dumpFile", (Object) null );
+        setInternalState( dumper, "dumpStreamFile", (Object) null );
+        setInternalState( dumper, "binaryDumpStreamFile", (Object) null );
+    }
+
     @Test
     public void canExecuteUnixPs()
     {
@@ -150,6 +163,60 @@ public class PpidCheckerTest
     }
 
     @Test
+    public void shouldBeStoppedCheckerWithError() throws Exception
+    {
+        String expectedPid = ManagementFactory.getRuntimeMXBean().getName().split( "@" )[0].trim();
+        DumpErrorSingleton.getSingleton().init( getTempDirectory(), "dump" );
+
+        PpidChecker checker = new PpidChecker( expectedPid );
+        checker.stop();
+
+        ProcessInfo processInfo = IS_OS_UNIX ? checker.unix() : checker.windows();
+        assertThat( processInfo.isError() ).isTrue();
+
+        File dump = DumpErrorSingleton.getSingleton().dumpText( null );
+
+        dump.deleteOnExit();
+
+        String error = new String( readAllBytes( dump.toPath() ) );
+
+        assertThat( error )
+            .contains( "<<exit>> <<0>>" )
+            .contains( "<<stopped>> <<true>>" );
+    }
+
+    @Test
+    public void shouldBeEmptyDump() throws Exception
+    {
+        String expectedPid = ManagementFactory.getRuntimeMXBean().getName().split( "@" )[0].trim();
+        DumpErrorSingleton.getSingleton().init( getTempDirectory(), "dump" );
+
+        PpidChecker checker = new PpidChecker( expectedPid );
+        Thread.currentThread().interrupt();
+
+        ProcessInfo processInfo = IS_OS_UNIX ? checker.unix() : checker.windows();
+        assertThat( processInfo.isError() ).isTrue();
+
+        // a hack to obtain the file
+        File dump = DumpErrorSingleton.getSingleton().dumpText( null );
+
+        dump.deleteOnExit();
+
+        String error = new String( readAllBytes( dump.toPath() ) ).trim();
+
+        String[] lines = error.split( "\r\n|\r|\n" );
+
+        assertThat( lines.length )
+            .isEqualTo( 2 );
+
+        assertThat( lines[0] )
+            .startsWith( "# Created at " );
+
+        assertThat( lines[1] )
+            .isEqualTo( "null" );
+    }
+
+    @Test
     public void shouldNotFindSuchPID()
     {
         PpidChecker checker = new PpidChecker( "1000000" );