Fix race-condition-induced dead lock on replay restart in 1.14+
MC clears it scheduled tasks on disconnect. If we don't wait for that to have happened on the async sender, then we might loose some of the initial handshake packets (resulting in a dead lock in fabric's registry syncing code).
This commit is contained in:
@@ -42,6 +42,8 @@ import net.minecraft.util.NonBlockingThreadExecutor;
|
|||||||
//$$ import com.google.common.util.concurrent.ListenableFutureTask;
|
//$$ import com.google.common.util.concurrent.ListenableFutureTask;
|
||||||
//$$ import net.minecraft.resources.FolderPack;
|
//$$ import net.minecraft.resources.FolderPack;
|
||||||
//$$ import net.minecraftforge.eventbus.api.SubscribeEvent;
|
//$$ import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
//$$ import java.util.Queue;
|
||||||
|
//$$ import java.util.concurrent.FutureTask;
|
||||||
//$$
|
//$$
|
||||||
//#if MC>=11300
|
//#if MC>=11300
|
||||||
//$$ import com.replaymod.core.versions.LangResourcePack;
|
//$$ import com.replaymod.core.versions.LangResourcePack;
|
||||||
@@ -89,8 +91,9 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.FutureTask;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import static com.replaymod.core.versions.MCVer.*;
|
import static com.replaymod.core.versions.MCVer.*;
|
||||||
|
|
||||||
@@ -385,16 +388,28 @@ public class ReplayMod implements
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void runSync(Runnable runnable) {
|
/**
|
||||||
|
* Execute the given runnable on the main client thread, returning only after it has been run (or after 30 seconds).
|
||||||
|
*/
|
||||||
|
public void runSync(Runnable runnable) throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
if (mc.isOnThread()) {
|
if (mc.isOnThread()) {
|
||||||
//#else
|
|
||||||
//$$ if (mc.isCallingFromMinecraftThread()) {
|
|
||||||
//#endif
|
|
||||||
runnable.run();
|
runnable.run();
|
||||||
} else {
|
} else {
|
||||||
runLater(runnable);
|
executor.executeFuture(() -> {
|
||||||
|
runnable.run();
|
||||||
|
return null;
|
||||||
|
}).get(30, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
//#else
|
||||||
|
//$$ if (mc.isCallingFromMinecraftThread()) {
|
||||||
|
//$$ runnable.run();
|
||||||
|
//$$ } else {
|
||||||
|
//$$ FutureTask<Void> future = new FutureTask<>(runnable, null);
|
||||||
|
//$$ runLater(future);
|
||||||
|
//$$ future.get(30, TimeUnit.SECONDS);
|
||||||
|
//$$ }
|
||||||
|
//#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ import net.minecraft.network.ClientConnection;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
//#if MC>=11300
|
//#if MC>=11300
|
||||||
import com.replaymod.replay.mixin.EntityLivingBaseAccessor;
|
import com.replaymod.replay.mixin.EntityLivingBaseAccessor;
|
||||||
@@ -162,18 +164,22 @@ public class ReplayHandler {
|
|||||||
channel.close();
|
channel.close();
|
||||||
|
|
||||||
// Force re-creation of camera entity by unloading the previous world
|
// Force re-creation of camera entity by unloading the previous world
|
||||||
ReplayMod.instance.runSync(() -> {
|
try {
|
||||||
//#if MC>=11300
|
ReplayMod.instance.runSync(() -> {
|
||||||
mc.mouse.unlockCursor();
|
//#if MC>=11300
|
||||||
//#else
|
mc.mouse.unlockCursor();
|
||||||
//$$ mc.setIngameNotInFocus();
|
//#else
|
||||||
//#endif
|
//$$ mc.setIngameNotInFocus();
|
||||||
//#if MC>=11400
|
//#endif
|
||||||
mc.disconnect();
|
//#if MC>=11400
|
||||||
//#else
|
mc.disconnect();
|
||||||
//$$ mc.loadWorld(null);
|
//#else
|
||||||
//#endif
|
//$$ mc.loadWorld(null);
|
||||||
});
|
//#endif
|
||||||
|
});
|
||||||
|
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||||
|
LOGGER.error("Failed to properly restart (shutdown) replay:", e);
|
||||||
|
}
|
||||||
|
|
||||||
restrictions = new Restrictions();
|
restrictions = new Restrictions();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user