Fix potential deadlock when chunkload raises non-IO exception (#4861)
This commit is contained in:
parent
da888df463
commit
a98db5bef2
3 changed files with 84 additions and 15 deletions
|
@ -41,7 +41,7 @@ public class ChunkIOExecutor
|
|||
private static final int PLAYERS_PER_THREAD = 50;
|
||||
|
||||
private static final Map<QueuedChunk, ChunkIOProvider> tasks = Maps.newConcurrentMap();
|
||||
private static final ThreadPoolExecutor pool = new ThreadPoolExecutor(BASE_THREADS, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
|
||||
private static final ThreadPoolExecutor pool = new ChunkIOThreadPoolExecutor(BASE_THREADS, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<Runnable>(),
|
||||
new ThreadFactory()
|
||||
{
|
||||
|
|
|
@ -26,7 +26,6 @@ import net.minecraft.nbt.NBTTagCompound;
|
|||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.world.ChunkDataEvent;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
@ -63,24 +62,29 @@ class ChunkIOProvider implements Runnable
|
|||
{
|
||||
synchronized(this)
|
||||
{
|
||||
Object[] data = null;
|
||||
try
|
||||
{
|
||||
data = this.loader.loadChunk__Async(chunkInfo.world, chunkInfo.x, chunkInfo.z);
|
||||
Object[] data = null;
|
||||
try
|
||||
{
|
||||
data = this.loader.loadChunk__Async(chunkInfo.world, chunkInfo.x, chunkInfo.z);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e); // Allow exception to bubble up to afterExecute
|
||||
}
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
this.nbt = (NBTTagCompound)data[1];
|
||||
this.chunk = (Chunk)data[0];
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
finally
|
||||
{
|
||||
FMLLog.log.error("Failed to load chunk async.", e);
|
||||
this.ran = true;
|
||||
this.notifyAll();
|
||||
}
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
this.nbt = (NBTTagCompound)data[1];
|
||||
this.chunk = (Chunk)data[0];
|
||||
}
|
||||
|
||||
this.ran = true;
|
||||
this.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,4 +136,9 @@ class ChunkIOProvider implements Runnable
|
|||
|
||||
this.callbacks.clear();
|
||||
}
|
||||
|
||||
public QueuedChunk getChunkInfo()
|
||||
{
|
||||
return chunkInfo;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.chunkio;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import net.minecraft.crash.CrashReportCategory;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
|
||||
class ChunkIOThreadPoolExecutor extends ThreadPoolExecutor {
|
||||
|
||||
public ChunkIOThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)
|
||||
{
|
||||
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterExecute(Runnable r, Throwable t)
|
||||
{
|
||||
if (t != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
FMLLog.log.error("Unhandled exception loading chunk:", t);
|
||||
QueuedChunk queuedChunk = ((ChunkIOProvider) r).getChunkInfo();
|
||||
FMLLog.log.error(queuedChunk);
|
||||
FMLLog.log.error(CrashReportCategory.getCoordinateInfo(queuedChunk.x << 4, 64, queuedChunk.z << 4));
|
||||
}
|
||||
catch (Throwable t2)
|
||||
{
|
||||
FMLLog.log.error(t2);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Make absolutely sure that we do not leave any deadlock case
|
||||
r.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue