From deef7321294a201f80c08d8dfa45304508e5d366 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Mon, 16 May 2011 21:11:28 -0500 Subject: [PATCH] Fix re-entrancy problem in FileHandler (shared buffer can cause corrupted or exchanged tiles) --- .../org/dynmap/web/handlers/FileHandler.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/dynmap/web/handlers/FileHandler.java b/src/main/java/org/dynmap/web/handlers/FileHandler.java index 8f51fc6c..4e116859 100644 --- a/src/main/java/org/dynmap/web/handlers/FileHandler.java +++ b/src/main/java/org/dynmap/web/handlers/FileHandler.java @@ -12,10 +12,16 @@ import org.dynmap.web.HttpHandler; import org.dynmap.web.HttpRequest; import org.dynmap.web.HttpResponse; import org.dynmap.web.HttpStatus; +import java.util.LinkedList; public abstract class FileHandler implements HttpHandler { protected static final Logger log = Logger.getLogger("Minecraft"); - private byte[] readBuffer = new byte[40960]; + //BUG-this breaks re-entrancy of this handler, which is called from multiple threads (one per request) + //private byte[] readBuffer = new byte[40960]; + //Replace with pool of buffers + private LinkedList bufferpool = new LinkedList(); + private Object lock = new Object(); + private static final int MAX_FREE_IN_POOL = 2; private static Map mimes = new HashMap(); static { @@ -59,6 +65,24 @@ public abstract class FileHandler implements HttpHandler { return path + "index.html"; } + private byte[] allocateReadBuffer() { + byte[] buf; + synchronized(lock) { + buf = bufferpool.poll(); + } + if(buf == null) { + buf = new byte[40960]; + } + return buf; + } + + private void freeReadBuffer(byte[] buf) { + synchronized(lock) { + if(bufferpool.size() < MAX_FREE_IN_POOL) + bufferpool.push(buf); + } + } + @Override public void handle(String path, HttpRequest request, HttpResponse response) throws Exception { InputStream fileInput = null; @@ -76,6 +100,7 @@ public abstract class FileHandler implements HttpHandler { response.fields.put(HttpField.ContentType, mimeType); response.status = HttpStatus.OK; OutputStream out = response.getBody(); + byte[] readBuffer = allocateReadBuffer(); try { int readBytes; while ((readBytes = fileInput.read(readBuffer)) > 0) { @@ -84,6 +109,8 @@ public abstract class FileHandler implements HttpHandler { } catch (IOException e) { fileInput.close(); throw e; + } finally { + freeReadBuffer(readBuffer); } fileInput.close(); } catch (Exception e) {