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 2019/07/19 11:59:33 UTC

[maven-surefire] branch buildfix updated (c16e744 -> 6aba396)

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

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


 discard c16e744  investigating build failure
 discard f22ed05  investigating build failure
 discard 75407f6  investigating build failure
 discard 3a3e205  investigating build failure
 discard c6d3f44  investigating build failure
 discard 634677e  investigating build failure
 discard 0752d4f  investigating build failure
 discard 7081d8b  investigating build failure
 discard b83ce90  investigating build failure
 discard 88b80b5  investigating build failure
 discard 8753c0d  investigating build failure
 discard bb8539c  investigating build failure
 discard b9226dc  investigating build failure
 discard 15d5aed  investigating build failure
 discard c39cb9e  investigating build failure
 discard 5b7ac26  investigating build failure
 discard 90dae28  investigating build failure
 discard a074c62  investigating build failure
 discard c4f0ca7  investigating build failure
 discard 139c2fa  investigating build failure
 discard 2ef4bf4  investigating build failure
 discard c5fed0a  investigating build failure
 discard f2ea4b5  investigating build failure
 discard 22a9ff5  investigating build failure
 discard 2fff907  investigating build failure
 discard 81f4415  investigating build failure
 discard e3bc1f6  investigating build failure
 discard 6a442eb  investigating build failure
 discard 279867a  investigating build failure
 discard 77a8a3c  investigating build failure
 discard b5c1f2a  investigating build failure
 discard b263ec2  investigating build failure
 discard a851970  investigating build failure
 discard 048ed7d  investigating build failure
 discard a1127f6  investigating build failure
 discard 6c6c01f  investigating build failure
 discard 7f3bfa5  investigating build failure
 discard 2f10581  investigating build failure
 discard 8c57aeb  investigating build failure
 discard 8acbf55  investigating build failure
 discard c335f97  investigating build failure
 discard 9790e20  investigating build failure
     new 6aba396  investigating build failure

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (c16e744)
            \
             N -- N -- N   refs/heads/buildfix (6aba396)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../jiras/Surefire946KillMainProcessInReusableForkIT.java |  2 +-
 .../src/test/java/junit44/environment/Basic02Test.java    | 14 ++++++++++++--
 .../src/test/java/junit44/environment/Basic03Test.java    | 14 ++++++++++++--
 .../src/test/java/junit44/environment/Basic04Test.java    | 15 +++++++++++++--
 .../src/test/java/junit44/environment/Basic05Test.java    | 14 ++++++++++++--
 .../src/test/java/junit44/environment/Basic06Test.java    | 14 ++++++++++++--
 .../src/test/java/junit44/environment/Basic07Test.java    | 14 ++++++++++++--
 .../src/test/java/junit44/environment/Basic08Test.java    | 15 +++++++++++++--
 .../src/test/java/junit44/environment/Basic09Test.java    | 14 ++++++++++++--
 .../src/test/java/junit44/environment/Basic10Test.java    | 15 +++++++++++++--
 10 files changed, 112 insertions(+), 19 deletions(-)


[maven-surefire] 01/01: investigating build failure

Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 6aba396d4eb0581dd92a8d539affd0c9e9430fb8
Author: tibordigana <ti...@apache.org>
AuthorDate: Mon Jul 15 04:35:35 2019 +0200

    investigating build failure
---
 Jenkinsfile                                        |  46 ++------
 .../maven/surefire/booter/CommandReader.java       |   3 +-
 .../apache/maven/surefire/booter/ForkedBooter.java | 117 +++++++++++++++++----
 surefire-its/pom.xml                               |   2 +-
 ...Surefire946KillMainProcessInReusableForkIT.java |  64 ++++++-----
 5 files changed, 143 insertions(+), 89 deletions(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 175c763..3a40f66 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -25,19 +25,17 @@ properties(
                                   artifactNumToKeepStr: '50',
                                   daysToKeepStr: env.BRANCH_NAME == 'master' ? '10' : '5',
                                   numToKeepStr: env.BRANCH_NAME == 'master' ? '5' : '3')
-        ),
-        disableConcurrentBuilds()
+        )
     ]
 )
 
-final def oses = ['linux':'ubuntu && !H24', 'windows':'Windows && !windows-2016-1']
+final def oses = ['linux':'ubuntu && !H24 && !H35', 'windows':'Windows']
 final def mavens = env.BRANCH_NAME == 'master' ? ['3.6.x', '3.2.x'] : ['3.6.x']
 // all non-EOL versions and the first EA
-final def jdks = [13, 12, 11, 8, 7]
+final def jdks = [8]
 
-final def options = ['-e', '-V', '-B', '-nsu', '-P', 'run-its']
+final def options = ['-e', '-V', '-B', '-nsu', '-DskipTests']
 final def goals = ['clean', 'install']
-final def goalsDepl = ['clean', 'install', 'jacoco:report']
 final Map stages = [:]
 
 oses.eachWithIndex { osMapping, indexOfOs ->
@@ -69,7 +67,7 @@ oses.eachWithIndex { osMapping, indexOfOs ->
                         def failsafeItPort = 8000 + 100 * indexOfMaven + 10 * indexOfJdk
                         def allOptions = options + ["-Dfailsafe-integration-test-port=${failsafeItPort}", "-Dfailsafe-integration-test-stop-port=${1 + failsafeItPort}"]
                         ws(dir: "${os == 'windows' ? "${TEMP}\\${BUILD_TAG}" : pwd()}") {
-                            buildProcess(stageKey, jdkName, jdkTestName, mvnName, first ? goalsDepl : goals, allOptions, mavenOpts, first)
+                            buildProcess(stageKey, jdkName, jdkTestName, mvnName, goals, allOptions, mavenOpts, first)
                         }
                     }
                 }
@@ -162,37 +160,7 @@ def buildProcess(String stageKey, String jdkName, String jdkTestName, String mvn
             }
         }
     } finally {
-        if (makeReports) {
-            openTasks(ignoreCase: true, canComputeNew: false, defaultEncoding: 'UTF-8', pattern: sourcesPatternCsv(),
-                    high: tasksViolationHigh(), normal: tasksViolationNormal(), low: tasksViolationLow())
-
-            jacoco(changeBuildStatus: false,
-                    execPattern: '**/*.exec',
-                    sourcePattern: sourcesPatternCsv(),
-                    classPattern: classPatternCsv())
-
-            junit(healthScaleFactor: 0.0,
-                    allowEmptyResults: true,
-                    keepLongStdio: true,
-                    testResults: testReportsPatternCsv())
-
-            if (currentBuild.result == 'UNSTABLE') {
-                currentBuild.result = 'FAILURE'
-            }
-        }
-
-        if (currentBuild.result != null && currentBuild.result != 'SUCCESS') {
-            if (fileExists('maven-failsafe-plugin/target/it')) {
-                zip(zipFile: "maven-failsafe-plugin--${stageKey}.zip", dir: 'maven-failsafe-plugin/target/it', archive: true)
-            }
-
-            if (fileExists('surefire-its/target')) {
-                zip(zipFile: "surefire-its--${stageKey}.zip", dir: 'surefire-its/target', archive: true)
-            }
-
-            archiveArtifacts(artifacts: "*--${stageKey}.zip", allowEmptyArchive: true, onlyIfSuccessful: false)
-        }
-        // clean up after ourselves to reduce disk space
+        sleep time: 25, unit: 'SECONDS'
         cleanWs()
     }
 }
@@ -205,6 +173,7 @@ static def sourcesPatternCsv() {
             '**/maven-surefire-report-plugin/src/main/java,' +
             '**/surefire-api/src/main/java,' +
             '**/surefire-booter/src/main/java,' +
+            '**/surefire-extensions-api/src/main/java,' +
             '**/surefire-grouper/src/main/java,' +
             '**/surefire-its/src/main/java,' +
             '**/surefire-logger-api/src/main/java,' +
@@ -220,6 +189,7 @@ static def classPatternCsv() {
             '**/maven-surefire-report-plugin/target/classes,' +
             '**/surefire-api/target/classes,' +
             '**/surefire-booter/target/classes,' +
+            '**/surefire-extensions-api/target/classes,' +
             '**/surefire-grouper/target/classes,' +
             '**/surefire-its/target/classes,' +
             '**/surefire-logger-api/target/classes,' +
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
index b4e303e..15b1dd0 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
@@ -207,8 +207,9 @@ public final class CommandReader
 
     public void stop()
     {
-        if ( state.compareAndSet( NEW, TERMINATED ) || state.compareAndSet( RUNNABLE, TERMINATED ) )
+        if ( !isStopped() )
         {
+            state.set( TERMINATED );
             makeQueueFull();
             listeners.clear();
             commandThread.interrupt();
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
index ebc1b27..0f8b8ad 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
@@ -30,6 +30,8 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
 import java.lang.reflect.InvocationTargetException;
 import java.security.AccessControlException;
 import java.security.AccessController;
@@ -47,6 +49,7 @@ import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.apache.maven.surefire.booter.SystemPropertyManager.setSystemProperties;
 import static org.apache.maven.surefire.util.ReflectionUtils.instantiateOneArg;
 import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThreadFactory;
+import static org.apache.maven.surefire.util.internal.StringUtils.NL;
 
 /**
  * The part of the booter that is unique to a forked vm.
@@ -62,12 +65,13 @@ public final class ForkedBooter
 {
     private static final long DEFAULT_SYSTEM_EXIT_TIMEOUT_IN_SECONDS = 30L;
     private static final long PING_TIMEOUT_IN_SECONDS = 30L;
-    private static final long ONE_SECOND_IN_MILLIS = 1000L;
+    private static final long ONE_SECOND_IN_MILLIS = 1_000L;
     private static final String LAST_DITCH_SHUTDOWN_THREAD = "surefire-forkedjvm-last-ditch-daemon-shutdown-thread-";
     private static final String PING_THREAD = "surefire-forkedjvm-ping-";
 
     private final CommandReader commandReader = CommandReader.getReader();
     private final ForkedChannelEncoder eventChannel = new ForkedChannelEncoder( System.out );
+    private final Semaphore exitBarrier = new Semaphore( 0 );
 
     private volatile long systemExitTimeoutInSeconds = DEFAULT_SYSTEM_EXIT_TIMEOUT_IN_SECONDS;
     private volatile PingScheduler pingScheduler;
@@ -92,7 +96,6 @@ public final class ForkedBooter
                 .init( providerConfiguration.getReporterConfiguration().getReportsDirectory(), dumpFileName );
 
         startupConfiguration = booterDeserializer.getProviderConfiguration();
-        systemExitTimeoutInSeconds = providerConfiguration.systemExitTimeout( DEFAULT_SYSTEM_EXIT_TIMEOUT_IN_SECONDS );
 
         AbstractPathConfiguration classpathConfiguration = startupConfiguration.getClasspathConfiguration();
 
@@ -129,7 +132,10 @@ public final class ForkedBooter
             DumpErrorSingleton.getSingleton().dumpException( t );
             eventChannel.consoleErrorLog( new LegacyPojoStackTraceWriter( "test subsystem", "no method", t ), false );
         }
-        acknowledgedExit();
+        finally
+        {
+            acknowledgedExit();
+        }
     }
 
     private Object createTestSet( TypeEncodedValue forkedTestSet, boolean readTestsFromCommandReader, ClassLoader cl )
@@ -175,7 +181,7 @@ public final class ForkedBooter
         AtomicBoolean pingDone = new AtomicBoolean( true );
         commandReader.addNoopListener( createPingHandler( pingDone ) );
 
-        PingScheduler pingMechanisms = new PingScheduler( createPingScheduler(),
+        /*PingScheduler pingMechanisms = new PingScheduler( createPingScheduler(),
                                                           ppid == null ? null : new PpidChecker( ppid ) );
         if ( pingMechanisms.pluginProcessChecker != null )
         {
@@ -185,7 +191,8 @@ public final class ForkedBooter
         Runnable pingJob = createPingJob( pingDone, pingMechanisms.pluginProcessChecker );
         pingMechanisms.pingScheduler.scheduleAtFixedRate( pingJob, 0L, PING_TIMEOUT_IN_SECONDS, SECONDS );
 
-        return pingMechanisms;
+        return pingMechanisms;*/
+        return null;
     }
 
     private Runnable processCheckerJob( final PingScheduler pingMechanism )
@@ -202,7 +209,11 @@ public final class ForkedBooter
                                  && !pingMechanism.pingScheduler.isShutdown() )
                     {
                         DumpErrorSingleton.getSingleton()
-                                .dumpText( "Killing self fork JVM. Maven process died." );
+                                .dumpText( "Killing self fork JVM. Maven process died."
+                                        + NL
+                                        + "Thread dump before killing the process (" + getProcessName() + "):"
+                                        + NL
+                                        + generateThreadDump() );
 
                         kill();
                     }
@@ -239,17 +250,33 @@ public final class ForkedBooter
                 if ( shutdown.isKill() )
                 {
                     DumpErrorSingleton.getSingleton()
-                            .dumpText( "Killing self fork JVM. Received SHUTDOWN command from Maven shutdown hook." );
+                            .dumpText( "Killing self fork JVM. Received SHUTDOWN command from Maven shutdown hook."
+                                    + NL
+                                    + "Thread dump before killing the process (" + getProcessName() + "):"
+                                    + NL
+                                    + generateThreadDump() );
                     kill();
                 }
                 else if ( shutdown.isExit() )
                 {
                     cancelPingScheduler();
                     DumpErrorSingleton.getSingleton()
-                            .dumpText( "Exiting self fork JVM. Received SHUTDOWN command from Maven shutdown hook." );
+                            .dumpText( "Exiting self fork JVM. Received SHUTDOWN command from Maven shutdown hook."
+                                    + NL
+                                    + "Thread dump before exiting the process (" + getProcessName() + "):"
+                                    + NL
+                                    + generateThreadDump() );
+                    exitBarrier.release();
                     exit1();
                 }
-                // else refers to shutdown=testset, but not used now, keeping reader open
+                else
+                {
+                    // else refers to shutdown=testset, but not used now, keeping reader open
+                    DumpErrorSingleton.getSingleton()
+                            .dumpText( "Thread dump for process (" + getProcessName() + "):"
+                                    + NL
+                                    + generateThreadDump() );
+                }
             }
         };
     }
@@ -267,7 +294,11 @@ public final class ForkedBooter
                     if ( !hasPing )
                     {
                         DumpErrorSingleton.getSingleton()
-                                .dumpText( "Killing self fork JVM. PING timeout elapsed." );
+                                .dumpText( "Killing self fork JVM. PING timeout elapsed."
+                                        + NL
+                                        + "Thread dump before killing the process (" + getProcessName() + "):"
+                                        + NL
+                                        + generateThreadDump() );
 
                         kill();
                     }
@@ -295,20 +326,19 @@ public final class ForkedBooter
 
     private void acknowledgedExit()
     {
-        final Semaphore barrier = new Semaphore( 0 );
         commandReader.addByeAckListener( new CommandListener()
                                           {
                                               @Override
                                               public void update( Command command )
                                               {
-                                                  barrier.release();
+                                                  exitBarrier.release();
                                               }
                                           }
         );
         eventChannel.bye();
         launchLastDitchDaemonShutdownThread( 0 );
         long timeoutMillis = max( systemExitTimeoutInSeconds * ONE_SECOND_IN_MILLIS, ONE_SECOND_IN_MILLIS );
-        acquireOnePermit( barrier, timeoutMillis );
+        acquireOnePermit( exitBarrier, timeoutMillis );
         cancelPingScheduler();
         commandReader.stop();
         System.exit( 0 );
@@ -342,14 +372,24 @@ public final class ForkedBooter
     @SuppressWarnings( "checkstyle:emptyblock" )
     private void launchLastDitchDaemonShutdownThread( final int returnCode )
     {
-        getJvmTerminator().schedule( new Runnable()
-                                        {
-                                            @Override
-                                            public void run()
-                                            {
-                                                kill( returnCode );
-                                            }
-                                        }, systemExitTimeoutInSeconds, SECONDS
+        getJvmTerminator()
+                .schedule( new Runnable()
+                {
+                    @Override
+                    public void run()
+                    {
+                        DumpErrorSingleton.getSingleton()
+                                .dumpText( "Thread dump for process ("
+                                        + getProcessName()
+                                        + ") after "
+                                        + systemExitTimeoutInSeconds
+                                        + " seconds shutdown timeout:"
+                                        + NL
+                                        + generateThreadDump() );
+
+                        kill( returnCode );
+                    }
+                }, systemExitTimeoutInSeconds, SECONDS
         );
     }
 
@@ -422,9 +462,10 @@ public final class ForkedBooter
     private static ScheduledExecutorService createPingScheduler()
     {
         ThreadFactory threadFactory = newDaemonThreadFactory( PING_THREAD + PING_TIMEOUT_IN_SECONDS + "s" );
-        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor( 1, threadFactory );
-        executor.setKeepAliveTime( 3L, SECONDS );
+        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor( 2, threadFactory );
+        //executor.setKeepAliveTime( 3L, SECONDS );
         executor.setMaximumPoolSize( 2 );
+        executor.prestartAllCoreThreads();
         return executor;
     }
 
@@ -472,4 +513,34 @@ public final class ForkedBooter
             return pingScheduler.isShutdown();
         }
     }
+
+    public static String generateThreadDump()
+    {
+        StringBuilder dump = new StringBuilder();
+        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+        ThreadInfo[] threadInfos = threadMXBean.getThreadInfo( threadMXBean.getAllThreadIds(), 100 );
+        for ( ThreadInfo threadInfo : threadInfos )
+        {
+            dump.append( '"' );
+            dump.append( threadInfo.getThreadName() );
+            dump.append( "\" " );
+            Thread.State state = threadInfo.getThreadState();
+            dump.append( "\n   java.lang.Thread.State: " );
+            dump.append( state );
+            StackTraceElement[] stackTraceElements = threadInfo.getStackTrace();
+            for ( StackTraceElement stackTraceElement : stackTraceElements )
+            {
+                dump.append( "\n        at " );
+                dump.append( stackTraceElement );
+            }
+            dump.append( "\n\n" );
+        }
+        return dump.toString();
+    }
+
+    private static String getProcessName()
+    {
+        return ManagementFactory.getRuntimeMXBean()
+                .getName();
+    }
 }
diff --git a/surefire-its/pom.xml b/surefire-its/pom.xml
index 2c4a7e6..cd9eb26 100644
--- a/surefire-its/pom.xml
+++ b/surefire-its/pom.xml
@@ -175,7 +175,7 @@
                     <forkMode>once</forkMode>
                     <argLine>-server -Xmx64m -XX:+UseG1GC -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Djava.awt.headless=true -Djdk.net.URLClassPath.disableClassPathURLCheck=true</argLine>
                     <includes>
-                        <include>org/apache/**/*IT*.java</include>
+                        <include>org/apache/**/Surefire946KillMainProcessInReusableForkIT.java</include>
                     </includes>
                     <!-- Pass current surefire version to the main suite so that it -->
                     <!-- can forward to all integration test projects. SUREFIRE-513 -->
diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire946KillMainProcessInReusableForkIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire946KillMainProcessInReusableForkIT.java
index a5740c0..8af9afd 100644
--- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire946KillMainProcessInReusableForkIT.java
+++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire946KillMainProcessInReusableForkIT.java
@@ -19,48 +19,60 @@ package org.apache.maven.surefire.its.jiras;
  * under the License.
  */
 
+import com.googlecode.junittoolbox.ParallelParameterized;
 import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
 
+import java.util.ArrayList;
+
+@RunWith( ParallelParameterized.class )
 public class Surefire946KillMainProcessInReusableForkIT
     extends SurefireJUnit4IntegrationTestCase
 {
-    // there are 10 test classes that each would wait 2 seconds.
-    private static final int TEST_SLEEP_TIME = 2000;
+    // there are 10 test classes that each would wait 3.5 seconds.
+    private static final int TEST_SLEEP_TIME = 3_500;
 
-    @BeforeClass
-    public static void installSelfdestructPlugin()
-    {
-        unpack( Surefire946KillMainProcessInReusableForkIT.class, "surefire-946-self-destruct-plugin", "plugin" ).executeInstall();
-    }
+    @Parameter( 0 )
+    public String shutdownMavenMethod;
 
-    @Test( timeout = 30000 )
-    public void testHalt()
-    {
-        doTest( "halt" );
-    }
+    @Parameter( 1 )
+    public String shutdownSurefireMethod;
 
-    @Test( timeout = 30000 )
-    public void testExit()
+    @Parameters( name = "{0}-{1}")
+    public static Iterable<Object[]> data()
     {
-        doTest( "exit" );
+        ArrayList<Object[]> args = new ArrayList<>();
+        args.add( new Object[] { "halt", "exit" } );
+        args.add( new Object[] { "halt", "kill" } );
+        args.add( new Object[] { "exit", "exit" } );
+        args.add( new Object[] { "exit", "kill" } );
+        args.add( new Object[] { "interrupt", "exit" } );
+        args.add( new Object[] { "interrupt", "kill" } );
+        return args;
     }
 
-    @Test( timeout = 30000 )
-    public void testInterrupt()
+    @BeforeClass
+    public static void installSelfdestructPlugin()
     {
-        doTest( "interrupt" );
+        unpack( Surefire946KillMainProcessInReusableForkIT.class, "surefire-946-self-destruct-plugin", "plugin" )
+                .executeInstall();
     }
 
-    private void doTest( String method )
+    @Test( timeout = 60_000 )
+    public void test()
     {
-        unpack( "surefire-946-killMainProcessInReusableFork" )
-            .sysProp( "selfdestruct.timeoutInMillis", "5000" )
-            .sysProp( "selfdestruct.method", method )
-            .sysProp( "testSleepTime", String.valueOf( TEST_SLEEP_TIME ) )
-            .addGoal( "org.apache.maven.plugins.surefire:maven-selfdestruct-plugin:selfdestruct" )
-            .setForkJvm()
-            .forkPerThread().threadCount( 1 ).reuseForks( true ).maven().withFailure().executeTest();
+        unpack( "surefire-946-killMainProcessInReusableFork",
+                "-" + shutdownMavenMethod + "-" + shutdownSurefireMethod )
+                .sysProp( "surefire.shutdown", shutdownSurefireMethod )
+                .sysProp( "selfdestruct.timeoutInMillis", "5000" )
+                .sysProp( "selfdestruct.method", shutdownMavenMethod )
+                .sysProp( "testSleepTime", String.valueOf( TEST_SLEEP_TIME ) )
+                .addGoal( "org.apache.maven.plugins.surefire:maven-selfdestruct-plugin:selfdestruct" )
+                .setForkJvm()
+                .forkPerThread().threadCount( 1 ).reuseForks( true ).maven().withFailure().executeTest();
     }
 }