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/04/22 22:11:54 UTC

[maven-surefire] branch docker updated: GC pauses (> 15 sec) detected in the middle of period (30 sec), and GC pauses (7.5 sec) detected after the period.

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

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


The following commit(s) were added to refs/heads/docker by this push:
     new 551f6b6  GC pauses (> 15 sec) detected in the middle of period (30 sec), and GC pauses (7.5 sec) detected after the period.
551f6b6 is described below

commit 551f6b6b8c0977f5a809945fa2c3e32d34ef5bc5
Author: tibordigana <ti...@apache.org>
AuthorDate: Tue Apr 23 00:10:55 2019 +0200

    GC pauses (> 15 sec) detected in the middle of period (30 sec), and GC pauses (7.5 sec) detected after the period.
---
 .../apache/maven/surefire/booter/ForkedBooter.java | 75 ++++++++++++++--------
 1 file changed, 48 insertions(+), 27 deletions(-)

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 de9083f..b0a75b5 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
@@ -38,7 +38,8 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.atomic.AtomicMarkableReference;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import static java.lang.Math.max;
 import static java.lang.Thread.currentThread;
@@ -61,10 +62,11 @@ import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDae
 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 PING_TIMEOUT_MAX_DELAY_IN_SECONDS = 15L; // due to GC pauses
-    private static final long PING_MAX_TIMEOUT_IN_SECONDS = PING_TIMEOUT_IN_SECONDS + PING_TIMEOUT_MAX_DELAY_IN_SECONDS;
+    private static final long PING_HALFPERIOD_IN_SECONDS = 15L;
+    private static final long PING_TIMEOUT_MAX_DELAY_IN_MILLIS = 7500L; // due to GC pauses
     private static final long ONE_SECOND_IN_MILLIS = 1000L;
+    private static final long PING_MAX_TIMEOUT_IN_MILLIS =
+            PING_HALFPERIOD_IN_SECONDS * ONE_SECOND_IN_MILLIS + PING_TIMEOUT_MAX_DELAY_IN_MILLIS;
     private static final String LAST_DITCH_SHUTDOWN_THREAD = "surefire-forkedjvm-last-ditch-daemon-shutdown-thread-";
     private static final String PING_THREAD = "surefire-forkedjvm-ping-";
 
@@ -177,8 +179,8 @@ public final class ForkedBooter
     private PingScheduler listenToShutdownCommands( Long ppid )
     {
         commandReader.addShutdownListener( createExitHandler() );
-        AtomicMarkableReference<Long> pingDone = new AtomicMarkableReference<>( System.currentTimeMillis(), true );
-        commandReader.addNoopListener( createPingHandler( pingDone ) );
+        PingPeriod pingPeriod = new PingPeriod();
+        commandReader.addNoopListener( createPingHandler( pingPeriod ) );
 
         PingScheduler pingMechanisms = new PingScheduler( createPingScheduler(),
                                                           ppid == null ? null : new PpidChecker( ppid ) );
@@ -187,8 +189,8 @@ public final class ForkedBooter
             Runnable checkerJob = processCheckerJob( pingMechanisms );
             pingMechanisms.pingScheduler.scheduleWithFixedDelay( checkerJob, 0L, 1L, SECONDS );
         }
-        Runnable pingJob = createPingJob( pingDone, pingMechanisms.pluginProcessChecker );
-        pingMechanisms.pingScheduler.scheduleWithFixedDelay( pingJob, 0L, PING_TIMEOUT_IN_SECONDS, SECONDS );
+        Runnable pingJob = createPingJob( pingPeriod, pingMechanisms.pluginProcessChecker );
+        pingMechanisms.pingScheduler.scheduleWithFixedDelay( pingJob, 0L, PING_HALFPERIOD_IN_SECONDS, SECONDS );
 
         return pingMechanisms;
     }
@@ -221,14 +223,14 @@ public final class ForkedBooter
         };
     }
 
-    private CommandListener createPingHandler( final AtomicMarkableReference<Long> pingDone )
+    private CommandListener createPingHandler( final PingPeriod pingPeriod )
     {
         return new CommandListener()
         {
             @Override
             public void update( Command command )
             {
-                pingDone.set( System.currentTimeMillis(), true );
+                pingPeriod.pingDone.set( true );
             }
         };
     }
@@ -259,8 +261,7 @@ public final class ForkedBooter
         };
     }
 
-    private Runnable createPingJob( final AtomicMarkableReference<Long> pingDone,
-                                    final PpidChecker pluginProcessChecker  )
+    private Runnable createPingJob( final PingPeriod pingPeriod, final PpidChecker pluginProcessChecker  )
     {
         return new Runnable()
         {
@@ -269,22 +270,26 @@ public final class ForkedBooter
             {
                 if ( !canUseNewPingMechanism( pluginProcessChecker ) )
                 {
-                    boolean hasPing;
-                    long lastCheck;
-                    do
+                    int periodCounter = pingPeriod.pingTimeoutCounter.getAndIncrement();
+                    if ( periodCounter % 2 == 0 )
                     {
-                        hasPing = pingDone.isMarked();
-                        lastCheck = pingDone.getReference();
-                    } while ( pingDone.compareAndSet( lastCheck, lastCheck, hasPing, false ) );
-
-                    boolean longGcPausesDetected = System.currentTimeMillis() - lastCheck > PING_MAX_TIMEOUT_IN_SECONDS;
-
-                    if ( !longGcPausesDetected && !hasPing )
+                        boolean longGcPausesDetected = pingPeriod.firstHalfPeriod >= PING_MAX_TIMEOUT_IN_MILLIS;
+                        pingPeriod.periodStartTime = System.currentTimeMillis();
+                        longGcPausesDetected |=
+                                pingPeriod.periodStartTime - pingPeriod.halfPeriodTime >= PING_MAX_TIMEOUT_IN_MILLIS;
+                        boolean hasPing = pingPeriod.pingDone.getAndSet( false );
+                        if ( !longGcPausesDetected && hasPing )
+                        {
+                            DumpErrorSingleton.getSingleton()
+                                    .dumpText( "Killing self fork JVM. PING timeout elapsed." );
+
+                            kill();
+                        }
+                    }
+                    else
                     {
-                        DumpErrorSingleton.getSingleton()
-                                .dumpText( "Killing self fork JVM. PING timeout elapsed." );
-
-                        kill();
+                        pingPeriod.halfPeriodTime = System.currentTimeMillis();
+                        pingPeriod.firstHalfPeriod = pingPeriod.halfPeriodTime - pingPeriod.periodStartTime;
                     }
                 }
             }
@@ -436,7 +441,7 @@ public final class ForkedBooter
 
     private static ScheduledExecutorService createPingScheduler()
     {
-        ThreadFactory threadFactory = newDaemonThreadFactory( PING_THREAD + PING_TIMEOUT_IN_SECONDS + "s" );
+        ThreadFactory threadFactory = newDaemonThreadFactory( PING_THREAD + PING_HALFPERIOD_IN_SECONDS + "s" );
         ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor( 1, threadFactory );
         executor.setKeepAliveTime( 3L, SECONDS );
         executor.setMaximumPoolSize( 2 );
@@ -487,4 +492,20 @@ public final class ForkedBooter
             return pingScheduler.isShutdown();
         }
     }
+
+    private static class PingPeriod
+    {
+        private final AtomicInteger pingTimeoutCounter = new AtomicInteger();
+        private final AtomicBoolean pingDone = new AtomicBoolean();
+        private volatile long halfPeriodTime;
+        private volatile long periodStartTime;
+        private volatile long firstHalfPeriod;
+
+        private PingPeriod()
+        {
+            long now = System.currentTimeMillis();
+            periodStartTime = now;
+            halfPeriodTime = now;
+        }
+    }
 }