fix: race condition in EnumWrappers#initialize (#3121)

Adds synchronization primitives inside the initialization function to
ensure that when the function returns, everything is guaranteed to be
initialized.

Fixes #3120
This commit is contained in:
Diogo Correia 2024-07-23 03:56:48 +01:00 committed by GitHub
parent f227b17f5f
commit 9fc68d4b6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -664,6 +664,7 @@ public abstract class EnumWrappers {
private static Class<?> CHAT_FORMATTING_CLASS = null;
private static Class<?> CLIENT_INTENT_CLASS = null;
private static boolean INITIALIZING = false;
private static boolean INITIALIZED = false;
private static Map<Class<?>, EquivalentConverter<?>> FROM_NATIVE = new HashMap<>();
private static Map<Class<?>, EquivalentConverter<?>> FROM_WRAPPER = new HashMap<>();
@ -676,7 +677,14 @@ public abstract class EnumWrappers {
if (INITIALIZED)
return;
INITIALIZED = true;
synchronized (EnumWrappers.class) {
// Recheck initialization status inside the lock
if (INITIALIZING || INITIALIZED)
return;
// Prevent circular calls to initialize during initialization
// (certain methods below indirectly call initialize again)
INITIALIZING = true;
PROTOCOL_CLASS = MinecraftReflection.getEnumProtocolClass();
CLIENT_COMMAND_CLASS = getEnum(PacketType.Play.Client.CLIENT_COMMAND.getPacketClass(), 0);
@ -790,6 +798,9 @@ public abstract class EnumWrappers {
if (ENTITY_POSE_CLASS != null) {
associate(ENTITY_POSE_CLASS, EntityPose.class, getEntityPoseConverter());
}
INITIALIZED = true;
}
}
private static void associate(Class<?> nativeClass, Class<?> wrapperClass, EquivalentConverter<?> converter) {