Just Enough Items (JEI)

Just Enough Items (JEI)

387M Downloads

[Bug]: Config File Watcher thread never exits

DBotThePony opened this issue ยท 2 comments

commented

Steps to Reproduce the Bug

  1. Depend on JEI runtime in your gradle buildscript
  2. Execute task runData
  3. Task never finishes

Expected Behavior

Game/JVM exits normally

Actual Behavior

Game/JVM never exits

Mod Pack URL (Optional)

No response

Mod Pack Version (Optional)

No response

Extra Notes (Optional)

This is caused by JEI "config save delay" thread being indefinitely alive and not marked as daemon, first is a bug (being alive while having no jobs), second is not (it is not a daemon thread to avoid getting cut short config while writing config back to disk)

"JEI Config Save Delay" #42 prio=5 os_prio=0 cpu=0.00ms elapsed=112.42s tid=0x000001e866b1f3f0 nid=0x6bec in Object.wait()  [0x000000a6ed4ff000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait([email protected]/Native Method)
        - waiting on <0x000000040cc737c8> (a java.util.TaskQueue)
        at java.lang.Object.wait([email protected]/Object.java:338)
        at java.util.TimerThread.mainLoop([email protected]/Timer.java:537)
        - locked <0x000000040cc737c8> (a java.util.TaskQueue)
        at java.util.TimerThread.run([email protected]/Timer.java:516)

   Locked ownable synchronizers:
        - None

"JEI Config File Watcher" #40 daemon prio=5 os_prio=0 cpu=0.00ms elapsed=112.39s tid=0x000001e866b20260 nid=0x5ae0 waiting on condition  [0x000000a6ed5ff000]
   java.lang.Thread.State: TIMED_WAITING (parking)
        at jdk.internal.misc.Unsafe.park([email protected]/Native Method)
        - parking to wait for  <0x000000040cc6f3e0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.parkNanos([email protected]/LockSupport.java:252)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos([email protected]/AbstractQueuedSynchronizer.java:1672)
        at java.util.concurrent.LinkedBlockingDeque.pollFirst([email protected]/LinkedBlockingDeque.java:515)
        at java.util.concurrent.LinkedBlockingDeque.poll([email protected]/LinkedBlockingDeque.java:677)
        at sun.nio.fs.AbstractWatchService.poll([email protected]/AbstractWatchService.java:108)
        at mezz.jei.common.config.file.FileWatcherThread.runIteration([email protected]/FileWatcherThread.java:96)
        at mezz.jei.common.config.file.FileWatcherThread.run([email protected]/FileWatcherThread.java:75)

   Locked ownable synchronizers:
        - None

latest.log

No response

commented

Code analysis:

This is caused by creating Timer without specifying isDaemon flag:

private static final Timer SAVE_DELAY_TIMER = new Timer("JEI Config Save Delay");

...which defaults to false:
2KANZnNFuJ

Timer's thread gets destroyed only if Timer#cancel() is called or it gets reclaimed by GC:

PGh43n9a2w

commented

Fixed via #3194