Fix random CMEs from NightConfigWatchThrottler

This commit is contained in:
embeddedt 2026-05-18 10:05:23 -04:00
parent a6c03e9928
commit ae20fa17c9
No known key found for this signature in database
GPG Key ID: A69433EC199B5613

View File

@ -22,7 +22,8 @@ public class NightConfigWatchThrottler {
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public static void throttle() { public static void throttle() {
Map watchedDirs = ObfuscationReflectionHelper.getPrivateValue(FileWatcher.class, FileWatcher.defaultInstance(), "watchedDirs"); Map watchedDirs = ObfuscationReflectionHelper.getPrivateValue(FileWatcher.class, FileWatcher.defaultInstance(), "watchedDirs");
ObfuscationReflectionHelper.setPrivateValue(FileWatcher.class, FileWatcher.defaultInstance(), new ForwardingMap() { Thread launchThread = Thread.currentThread();
Map watchedDirsWrapper = new ForwardingMap() {
@Override @Override
protected Map delegate() { protected Map delegate() {
return watchedDirs; return watchedDirs;
@ -44,13 +45,24 @@ public class NightConfigWatchThrottler {
public Iterator iterator() { public Iterator iterator() {
// iterator() is called at the beginning of each iteration of the watch loop, // iterator() is called at the beginning of each iteration of the watch loop,
// so it is a good spot to inject the delay. // so it is a good spot to inject the delay.
LockSupport.parkNanos(DELAY); if (Thread.currentThread() != launchThread) {
LockSupport.parkNanos(DELAY);
}
return super.iterator(); return super.iterator();
} }
}; };
} }
return cachedValues; return cachedValues;
} }
}, "watchedDirs"); };
// Force all classes related to the iterator to be loaded ahead of time. This is necessary to prevent
// a ConcurrentModificationException from being thrown inside ModLauncher when the NightConfig file
// watcher thread loads forwarding collection classes while the main thread is still mutating the
// launch plugin map.
//noinspection StatementWithEmptyBody
for (var ignored : watchedDirsWrapper.values()) {
}
ObfuscationReflectionHelper.setPrivateValue(FileWatcher.class, FileWatcher.defaultInstance(), watchedDirsWrapper, "watchedDirs");
} }
} }