From 2fc70088c149a0d2a7e9f48c5993e0fd9029763b Mon Sep 17 00:00:00 2001 From: wcrisman Date: Sun, 13 Jul 2014 12:54:10 -0700 Subject: [PATCH] Fixed newly introduced bug where by a blocking channel deadlocks because all content was read, but we attempted to read more anyway. --- .../com/foundation/web/StreamedContent.java | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/Foundation Web Application/src/com/foundation/web/StreamedContent.java b/Foundation Web Application/src/com/foundation/web/StreamedContent.java index fd5cb6b..5a06b5a 100644 --- a/Foundation Web Application/src/com/foundation/web/StreamedContent.java +++ b/Foundation Web Application/src/com/foundation/web/StreamedContent.java @@ -127,15 +127,36 @@ public int get(ByteBuffer buffer) { }//else// }//if// else { + boolean readFromChannel = this.buffer.remaining() == 0; + //Lazily create a buffer if necessary.// if(this.buffer == null) { this.buffer = ByteBuffer.allocate(2000); }//if// - //Read as many bytes from the channel as possible.// - this.buffer.compact(); - channel.read(this.buffer); - this.buffer.flip(); + //If there are bytes remaining in this.buffer AND we are about to read a new chunk header THEN figure out if we have at least enough bytes to read the chunk header (don't read more from the stream if true - could cause a deadlock, otherwise read more since there must be more to read).// + if(!readFromChannel && chunkSize == 0) { + StringBuffer chunkHeader = new StringBuffer(100); + this.buffer.mark(); + + //Read the next chunk header.// + while(this.buffer.hasRemaining() && (chunkHeader.length() < 2 || !(chunkHeader.charAt(chunkHeader.length() - 2) == '\r' && chunkHeader.charAt(chunkHeader.length() - 1) == '\n'))) { + chunkHeader.append((char) this.buffer.get()); + }//while// + + this.buffer.reset(); + + //If a chunk header was not readable then do read from the channel.// + readFromChannel = chunkHeader.length() < 2 || !(chunkHeader.charAt(chunkHeader.length() - 2) == '\r' && chunkHeader.charAt(chunkHeader.length() - 1) == '\n'); + }//if// + + //Only attempt a read IF there are no bytes in this.buffer OR we are reading the next chunk header and there are insufficient bytes in this.buffer to do so.// + if(readFromChannel) { + //Read as many bytes from the channel as possible.// + this.buffer.compact(); + channel.read(this.buffer); + this.buffer.flip(); + }//if// //Check to see if the chunk ends within this buffer.// if(this.buffer.remaining() > chunkSize) {