فهرست منبع

Add more context to threading detector crashes

malte0811 3 سال پیش
والد
کامیت
2057ca0c19

+ 1 - 1
common/build.gradle

@@ -38,7 +38,7 @@ dependencies {
 
 architectury {
     injectInjectables = false
-    common()
+    common("fabric", "forge")
 }
 
 jar {

+ 11 - 7
common/src/main/java/malte0811/ferritecore/util/SmallThreadingDetector.java

@@ -68,7 +68,7 @@ public class SmallThreadingDetector {
 
         private static void startCrash(SmallThreadDetectable owner, String name) {
             synchronized (MONITOR) {
-                ACTIVE_CRASHES.put(owner, new CrashingState(name));
+                ACTIVE_CRASHES.put(owner, new CrashingState(name, owner));
             }
         }
 
@@ -105,16 +105,18 @@ public class SmallThreadingDetector {
     }
 
     /**
-     * Data needed to produce the proper crash for race on a single SmallThreadingDetectable
+     * Data needed to produce the proper crash for race on a single SmallThreadDetectable
      */
     private static class CrashingState {
         final String name;
+        final SmallThreadDetectable owner;
         Thread acquireThread;
         Thread releaseThread;
         RuntimeException mainException;
 
-        private CrashingState(String name) {
+        private CrashingState(String name, SmallThreadDetectable owner) {
             this.name = name;
+            this.owner = owner;
         }
 
         public synchronized void waitUntilReady(ThreadRole role) {
@@ -141,15 +143,17 @@ public class SmallThreadingDetector {
         }
 
         private synchronized void waitUntilOrCrash(BooleanSupplier isReady) throws InterruptedException {
-            final long maxTotalTime = 10000;
+            final long maxTotalTime = 10_000;
             final var start = System.currentTimeMillis();
             while (!isReady.getAsBoolean()) {
-                if (System.currentTimeMillis() - start > maxTotalTime) {
-                    // Crash without both threads present if we don't manage to "find" them within 10 seconds
+                if (System.currentTimeMillis() - start > 6 * maxTotalTime) {
+                    // Crash without both threads present if we don't manage to "find" them within 60 seconds
                     // Happens e.g. when a release call is just missing, vanilla would hang indefinitely instead
                     // in this case
                     throw new RuntimeException(
-                            "Threading detector crash did not find other thread, missing release call?"
+                            "Threading detector crash did not find other thread, missing release call?"+
+                            " Owner: "+this.owner+" (ID hash: "+System.identityHashCode(this.owner)+")"+
+                            ", time: "+System.currentTimeMillis()
                     );
                 }
                 // Release lock on this for up to 10 seconds, or until the other threads are ready

+ 17 - 0
common/src/test/java/malte0811/ferritecore/util/SmallThreadingDetectorTest.java

@@ -75,6 +75,23 @@ class SmallThreadingDetectorTest {
         detec.checkAndUnlock();
     }
 
+    @Test
+    public void testDoubleAcquire() throws InterruptedException {
+        var obj = new OwnedObject();
+        SmallThreadingDetector.acquire(obj, "Test");
+        Assertions.assertThrows(RuntimeException.class, () -> SmallThreadingDetector.acquire(obj, "Test"));
+
+        AtomicBoolean locked = new AtomicBoolean(false);
+        runOnNewThread(() -> {
+            ThreadingDetector detec = new ThreadingDetector("test");
+            detec.checkAndLock();
+            detec.checkAndLock();
+            locked.set(true);
+        });
+        Thread.sleep(1000);
+        Assertions.assertFalse(locked.get());
+    }
+
     private static Thread runOnNewThread(Executable toRun) {
         return runOnNewThread(toRun, Throwable::printStackTrace);
     }

+ 1 - 1
gradle.properties

@@ -5,4 +5,4 @@ archives_base_name=ferritecore
 mod_version=4.2.0
 maven_group=malte0811.ferritecore
 fabric_loader_version=0.13.3
-forge_version=40.0.2
+forge_version=40.1.0