Merge 1.19.4 into 1.20

This commit is contained in:
embeddedt 2023-07-21 11:15:22 -04:00
commit 4031b65099
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
2 changed files with 32 additions and 12 deletions

View File

@ -43,7 +43,14 @@ public class ConfigFixer {
@Override @Override
public void accept(IConfigEvent modConfigEvent) { public void accept(IConfigEvent modConfigEvent) {
synchronized (this) { Object cfgObj = NightConfigFixer.toWriteSyncConfig(modConfigEvent.getConfig().getConfigData());
if(cfgObj != null) {
// don't synchronize on 'this' as it produces a deadlock when used alongside NightConfigFixer
synchronized (cfgObj) {
this.actualHandler.accept(modConfigEvent);
}
} else {
ModernFix.LOGGER.warn("Unable to sync on a {} config object", modConfigEvent.getConfig().getConfigData().getClass().getName());
this.actualHandler.accept(modConfigEvent); this.actualHandler.accept(modConfigEvent);
} }
} }

View File

@ -38,7 +38,7 @@ public class NightConfigFixer {
private static final Class<?> WATCHED_FILE = LamdbaExceptionUtils.uncheck(() -> Class.forName("com.electronwill.nightconfig.core.file.FileWatcher$WatchedFile")); private static final Class<?> WATCHED_FILE = LamdbaExceptionUtils.uncheck(() -> Class.forName("com.electronwill.nightconfig.core.file.FileWatcher$WatchedFile"));
private static final Field CHANGE_HANDLER = ObfuscationReflectionHelper.findField(WATCHED_FILE, "changeHandler"); private static final Field CHANGE_HANDLER = ObfuscationReflectionHelper.findField(WATCHED_FILE, "changeHandler");
private static final Class<?> WRITE_SYNC_CONFIG = LamdbaExceptionUtils.uncheck(() -> Class.forName("com.electronwill.nightconfig.core.file.WriteSyncFileConfig")); public static final Class<?> WRITE_SYNC_CONFIG = LamdbaExceptionUtils.uncheck(() -> Class.forName("com.electronwill.nightconfig.core.file.WriteSyncFileConfig"));
private static final Class<?> AUTOSAVE_CONFIG = LamdbaExceptionUtils.uncheck(() -> Class.forName("com.electronwill.nightconfig.core.file.AutosaveCommentedFileConfig")); private static final Class<?> AUTOSAVE_CONFIG = LamdbaExceptionUtils.uncheck(() -> Class.forName("com.electronwill.nightconfig.core.file.AutosaveCommentedFileConfig"));
private static final Field AUTOSAVE_FILECONFIG = ObfuscationReflectionHelper.findField(AUTOSAVE_CONFIG, "fileConfig"); private static final Field AUTOSAVE_FILECONFIG = ObfuscationReflectionHelper.findField(AUTOSAVE_CONFIG, "fileConfig");
@ -82,6 +82,25 @@ public class NightConfigFixer {
} }
} }
private static final Set<Class<?>> UNKNOWN_FILE_CONFIG_CLASSES = Collections.synchronizedSet(new ReferenceOpenHashSet<>());
public static Object toWriteSyncConfig(Object config) {
try {
if(WRITE_SYNC_CONFIG.isAssignableFrom(config.getClass())) {
return config;
} else if(AUTOSAVE_CONFIG.isAssignableFrom(config.getClass())) {
FileConfig fc = (FileConfig)AUTOSAVE_FILECONFIG.get(config);
return toWriteSyncConfig(fc);
} else {
if (UNKNOWN_FILE_CONFIG_CLASSES.add(config.getClass()))
ModernFixMixinPlugin.instance.logger.warn("Unexpected FileConfig class: {}", config.getClass().getName());
return null;
}
} catch(ReflectiveOperationException e) {
return null;
}
}
static class MonitoringConfigTracker implements Runnable { static class MonitoringConfigTracker implements Runnable {
private final Runnable configTracker; private final Runnable configTracker;
@ -89,17 +108,16 @@ public class NightConfigFixer {
this.configTracker = r; this.configTracker = r;
} }
private static final Set<Class<?>> UNKNOWN_FILE_CONFIG_CLASSES = Collections.synchronizedSet(new ReferenceOpenHashSet<>());
private void protectFromSaving(FileConfig config, Runnable runnable) throws ReflectiveOperationException { private void protectFromSaving(FileConfig config, Runnable runnable) throws ReflectiveOperationException {
if(WRITE_SYNC_CONFIG.isAssignableFrom(config.getClass())) { Object writeSyncConfig = toWriteSyncConfig(config);
if(writeSyncConfig != null) {
// keep trying to write, releasing the config lock each time in case something else needs to lock it // keep trying to write, releasing the config lock each time in case something else needs to lock it
// for any reason // for any reason
while(true) { while(true) {
// acquiring synchronized block here should in theory prevent any other concurrent loads/saves, based // acquiring synchronized block here should in theory prevent any other concurrent loads/saves, based
// off WriteSyncFileConfig implementation // off WriteSyncFileConfig implementation
synchronized (config) { synchronized (writeSyncConfig) {
if(CURRENTLY_WRITING.getBoolean(config)) { if(CURRENTLY_WRITING.getBoolean(writeSyncConfig)) {
ModernFixMixinPlugin.instance.logger.fatal("Config being written during load!!!"); ModernFixMixinPlugin.instance.logger.fatal("Config being written during load!!!");
try { Thread.sleep(500); } catch(InterruptedException e) { Thread.currentThread().interrupt(); } try { Thread.sleep(500); } catch(InterruptedException e) { Thread.currentThread().interrupt(); }
continue; continue;
@ -110,12 +128,7 @@ public class NightConfigFixer {
break; break;
} }
} }
} else if(AUTOSAVE_CONFIG.isAssignableFrom(config.getClass())) {
FileConfig fc = (FileConfig)AUTOSAVE_FILECONFIG.get(config);
protectFromSaving(fc, runnable);
} else { } else {
if(UNKNOWN_FILE_CONFIG_CLASSES.add(config.getClass()))
ModernFixMixinPlugin.instance.logger.warn("Unexpected FileConfig class: {}", config.getClass().getName());
runnable.run(); runnable.run();
} }
} }