Skip to content

Commit f725bb5

Browse files
committed
fix EarlyConfig NPE from race conditions
1 parent 6d82ff2 commit f725bb5

File tree

3 files changed

+47
-16
lines changed

3 files changed

+47
-16
lines changed

src/main/java/com/falsepattern/lib/internal/config/EarlyConfig.java

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,21 @@
2424
package com.falsepattern.lib.internal.config;
2525

2626
import com.falsepattern.lib.StableAPI;
27+
import com.falsepattern.lib.internal.FalsePatternLib;
28+
import com.falsepattern.lib.internal.Tags;
2729
import com.falsepattern.lib.internal.core.LowLevelCallMultiplexer;
2830
import com.google.gson.Gson;
31+
import com.google.gson.GsonBuilder;
2932
import com.google.gson.annotations.Expose;
3033
import lombok.Data;
3134
import lombok.SneakyThrows;
3235
import lombok.experimental.Accessors;
3336
import lombok.val;
37+
import org.apache.logging.log4j.LogManager;
38+
import org.apache.logging.log4j.Logger;
39+
import org.jetbrains.annotations.NotNull;
3440

41+
import java.io.IOException;
3542
import java.nio.charset.StandardCharsets;
3643
import java.nio.file.Files;
3744

@@ -43,22 +50,45 @@ public class EarlyConfig {
4350
@StableAPI.Expose(since = "__INTERNAL__")
4451
private boolean enableLibraryDownloads;
4552

46-
private static EarlyConfig instance = null;
53+
private static volatile EarlyConfig instance = null;
4754

48-
@SneakyThrows
49-
public static EarlyConfig load() {
50-
if (instance != null)
51-
return instance;
52-
val configFile = LowLevelCallMultiplexer.gameDir().resolve("config").resolve("falsepatternlib-early.json");
53-
val gson = new Gson();
54-
EarlyConfig config;
55-
if (!Files.exists(configFile)) {
55+
private static final Logger LOG = LogManager.getLogger(Tags.MODNAME + " Early Config");
56+
57+
public static @NotNull EarlyConfig getInstance() {
58+
val config = instance;
59+
if (config != null)
60+
return config;
61+
return loadFromDisk();
62+
}
63+
64+
private static synchronized @NotNull EarlyConfig loadFromDisk() {
65+
var config = instance;
66+
if (config != null) {
67+
return config;
68+
}
69+
val configDir = LowLevelCallMultiplexer.gameDir().resolve("config");
70+
val configFile = configDir.resolve("falsepatternlib-early.json");
71+
val gson = new GsonBuilder().setPrettyPrinting().create();
72+
try {
73+
if (!Files.exists(configDir)) {
74+
Files.createDirectories(configDir);
75+
}
76+
if (Files.exists(configFile)) {
77+
config = gson.fromJson(new String(Files.readAllBytes(configFile), StandardCharsets.UTF_8),
78+
EarlyConfig.class);
79+
}
80+
} catch (IOException e) {
81+
LOG.error("Failed to load from disk", e);
82+
}
83+
if (config == null) {
5684
config = new EarlyConfig();
5785
config.enableLibraryDownloads(true);
58-
} else {
59-
config = gson.fromJson(new String(Files.readAllBytes(configFile), StandardCharsets.UTF_8), EarlyConfig.class);
86+
try {
87+
Files.write(configFile, gson.toJson(config).getBytes(StandardCharsets.UTF_8));
88+
} catch (IOException e) {
89+
LOG.error("Failed to write to disk", e);
90+
}
6091
}
61-
Files.write(configFile, gson.toJson(config).getBytes(StandardCharsets.UTF_8));
6292
instance = config;
6393
return config;
6494
}

src/main/java/com/falsepattern/lib/internal/core/LowLevelCallMultiplexer.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import com.gtnewhorizons.retrofuturabootstrap.RfbApiImpl;
2727
import lombok.experimental.UtilityClass;
28+
import org.jetbrains.annotations.NotNull;
2829

2930
import net.minecraft.launchwrapper.Launch;
3031

@@ -56,7 +57,7 @@ public static List<URL> getClassPathSources() {
5657
}
5758
}
5859

59-
public static Path gameDir() {
60+
public static @NotNull Path gameDir() {
6061
if (rfbDetected) {
6162
return RFBLowLevel.gameDir();
6263
} else {
@@ -76,7 +77,7 @@ static List<URL> getClassPathSources() {
7677
return RfbApiImpl.INSTANCE.compatClassLoader().getSources();
7778
}
7879

79-
static Path gameDir() {
80+
static @NotNull Path gameDir() {
8081
return RfbApiImpl.INSTANCE.gameDirectory();
8182
}
8283
}
@@ -90,7 +91,7 @@ static List<URL> getClassPathSources() {
9091
return Launch.classLoader.getSources();
9192
}
9293

93-
static Path gameDir() {
94+
static @NotNull Path gameDir() {
9495
return Launch.minecraftHome == null ? Paths.get(".") : Launch.minecraftHome.toPath();
9596
}
9697
}

src/main/java/com/falsepattern/lib/internal/impl/dependencies/DependencyLoaderImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ private boolean tryLoadingExistingFile() {
805805
}
806806

807807
private void validateDownloadsAllowed() {
808-
if (!EarlyConfig.load().enableLibraryDownloads()) {
808+
if (!EarlyConfig.getInstance().enableLibraryDownloads()) {
809809
val errorMessage = "Failed to load library "
810810
+ groupId
811811
+ ":"

0 commit comments

Comments
 (0)