You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by dw...@apache.org on 2018/03/13 10:02:20 UTC

[2/2] lucene-solr:branch_7x: LUCENE-8201: improve the test a bit to try to diagnose timeouts on jenkins.

LUCENE-8201: improve the test a bit to try to diagnose timeouts on jenkins.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/4645553a
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/4645553a
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/4645553a

Branch: refs/heads/branch_7x
Commit: 4645553a55d574c760fe637418c91229db64f2bb
Parents: b2856a1
Author: Dawid Weiss <dw...@apache.org>
Authored: Tue Mar 13 11:01:30 2018 +0100
Committer: Dawid Weiss <dw...@apache.org>
Committed: Tue Mar 13 11:02:07 2018 +0100

----------------------------------------------------------------------
 .../lucene/codecs/TestCodecLoadingDeadlock.java | 53 ++++++++++++++++----
 1 file changed, 43 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4645553a/lucene/core/src/test/org/apache/lucene/codecs/TestCodecLoadingDeadlock.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/codecs/TestCodecLoadingDeadlock.java b/lucene/core/src/test/org/apache/lucene/codecs/TestCodecLoadingDeadlock.java
index 65f3016..8137f23 100644
--- a/lucene/core/src/test/org/apache/lucene/codecs/TestCodecLoadingDeadlock.java
+++ b/lucene/core/src/test/org/apache/lucene/codecs/TestCodecLoadingDeadlock.java
@@ -19,13 +19,16 @@ package org.apache.lucene.codecs;
 
 import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Locale;
 import java.util.Random;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
 import org.apache.lucene.util.LuceneTestCase;
@@ -42,12 +45,13 @@ import com.carrotsearch.randomizedtesting.RandomizedRunner;
 
 @RunWith(RandomizedRunner.class)
 public class TestCodecLoadingDeadlock extends Assert {
-  
+  private static int MAX_TIME_SECONDS = 30;
+
   @Test
   public void testDeadlock() throws Exception {
     LuceneTestCase.assumeFalse("This test fails on UNIX with Turkish default locale (https://issues.apache.org/jira/browse/LUCENE-6036)",
       new Locale("tr").getLanguage().equals(Locale.getDefault().getLanguage()));
-    
+
     // pick random codec names for stress test in separate process:
     final Random rnd = RandomizedContext.current().getRandom();
     Set<String> avail;
@@ -68,24 +72,39 @@ public class TestCodecLoadingDeadlock extends Assert {
       pfName,
       dvfName
     ).inheritIO().start();
-    if (p.waitFor(30, TimeUnit.SECONDS)) {
-      assertEquals("Process died abnormally", 0, p.waitFor());
+    if (p.waitFor(MAX_TIME_SECONDS * 2, TimeUnit.SECONDS)) {
+      assertEquals("Process died abnormally?", 0, p.waitFor());
     } else {
       p.destroyForcibly().waitFor();
-      fail("Process did not exit after 30 secs -> classloader deadlock?");
+      fail("Process did not exit after 60 secs?");
     }
   }
-  
-  // this method is called in a spawned process:
+
+  // This method is called in a spawned process.
   public static void main(final String... args) throws Exception {
     final String codecName = args[0];
     final String pfName = args[1];
     final String dvfName = args[2];
+
+    System.out.println(String.format(Locale.ROOT,
+        "codec: %s, pf: %s, dvf: %s", codecName, pfName, dvfName));
+
     final int numThreads = 14; // two times the modulo in switch statement below
-    final ExecutorService pool = Executors.newFixedThreadPool(numThreads, new NamedThreadFactory("deadlockchecker"));
+    final CopyOnWriteArrayList<Thread> allThreads = new CopyOnWriteArrayList<>();
+    final ExecutorService pool = Executors.newFixedThreadPool(numThreads, new NamedThreadFactory("deadlockchecker") {
+      @Override
+      public Thread newThread(Runnable r) {
+        Thread t = super.newThread(r);
+        allThreads.add(t);
+        return t;
+      }
+    });
+
     final CyclicBarrier barrier = new CyclicBarrier(numThreads);
     IntStream.range(0, numThreads).forEach(taskNo -> pool.execute(() -> {
       try {
+        // Await a common barrier point for all threads and then
+        // run racy code. This is intentional.
         barrier.await();
         switch (taskNo % 7) {
           case 0:
@@ -120,8 +139,22 @@ public class TestCodecLoadingDeadlock extends Assert {
         Runtime.getRuntime().halt(1); // signal failure to caller
       }
     }));
+
     pool.shutdown();
-    while (!pool.awaitTermination(1, TimeUnit.MINUTES));
-  }
 
+    if (!pool.awaitTermination(MAX_TIME_SECONDS, TimeUnit.SECONDS)) {
+      // Try to collect stacks so that we can better diagnose the failure.
+      System.err.println("Pool didn't return after " + MAX_TIME_SECONDS +
+          " seconds, classloader deadlock? Dumping stack traces.");
+
+      for (Thread t : allThreads) {
+        System.err.println(
+            "# Thread: " + t + ", " +
+            "state: " + t.getState() + ", " +
+            "stack:\n\t" + Arrays.stream(t.getStackTrace()).map(Object::toString)
+                .collect(Collectors.joining("\t")) + "\n");
+      }
+      Runtime.getRuntime().halt(1); // signal failure to caller
+    }
+  }
 }