Skip to content

Commit

Permalink
461452 Double release of buffer by HttpReceiverOverHTTP
Browse files Browse the repository at this point in the history
This commit is just a tidy up of the code to reduce the size of the race causing this problem.  It is not a fix.
  • Loading branch information
gregw committed Mar 5, 2015
1 parent 40ad8dc commit 8cbab09
Showing 1 changed file with 30 additions and 24 deletions.
Expand Up @@ -64,27 +64,29 @@ protected ByteBuffer getResponseBuffer()

public void receive()
{
buffer = acquireBuffer();
process(buffer);
if (buffer==null)
acquireBuffer();
process();
}

private ByteBuffer acquireBuffer()
private void acquireBuffer()
{
HttpClient client = getHttpDestination().getHttpClient();
ByteBufferPool bufferPool = client.getByteBufferPool();
return bufferPool.acquire(client.getResponseBufferSize(), true);
buffer = bufferPool.acquire(client.getResponseBufferSize(), true);
}

private void releaseBuffer(ByteBuffer buffer)
private void releaseBuffer()
{
assert this.buffer == buffer;
if (buffer==null)
throw new IllegalStateException();
HttpClient client = getHttpDestination().getHttpClient();
ByteBufferPool bufferPool = client.getByteBufferPool();
bufferPool.release(buffer);
this.buffer = null;
buffer = null;
}

private void process(ByteBuffer buffer)
private void process()
{
try
{
Expand All @@ -97,11 +99,11 @@ private void process(ByteBuffer buffer)
{
if (LOG.isDebugEnabled())
LOG.debug("{} closed", connection);
releaseBuffer(buffer);
releaseBuffer();
return;
}

if (!parse(buffer))
if (parse())
return;

int read = endPoint.fill(buffer);
Expand All @@ -110,18 +112,18 @@ private void process(ByteBuffer buffer)

if (read > 0)
{
if (!parse(buffer))
if (parse())
return;
}
else if (read == 0)
{
releaseBuffer(buffer);
releaseBuffer();
fillInterested();
return;
}
else
{
releaseBuffer(buffer);
releaseBuffer();
shutdown();
return;
}
Expand All @@ -131,7 +133,7 @@ else if (read == 0)
{
if (LOG.isDebugEnabled())
LOG.debug(x);
releaseBuffer(buffer);
releaseBuffer();
failAndClose(x);
}
}
Expand All @@ -140,24 +142,28 @@ else if (read == 0)
* Parses a HTTP response from the given {@code buffer}.
*
* @param buffer the response bytes
* @return true to indicate that the parsing may proceed (for example with another response),
* false to indicate that the parsing should be interrupted (and will be resumed by another thread).
* @return true to indicate that parsing should be interrupted (and will be resumed by another thread).
*/
private boolean parse(ByteBuffer buffer)
private boolean parse()
{
// Must parse even if the buffer is fully consumed, to allow the
// parser to advance from asynchronous content to response complete.
boolean handle = parser.parseNext(buffer);
if (LOG.isDebugEnabled())
LOG.debug("Parsed {}, remaining {} {}", handle, buffer.remaining(), parser);

if (!handle)
return true;
if (handle)
{
// There are several cases here:
// a) the content is being handled asynchronously and resume will eventually call process(). Return false.
// b) the content has already been handled asynchronously, resume called process and processing is ongoing. Return false.
// c) the content has already been handled asynchronously, resume called process which completed the response. Return false.
// d) This call to parse called parseNext, which completed the response. Return true

return !parser.isStart(); // TODO this is insufficient to distinguish the last to cases above
}

// If the parser returns true, we need to differentiate two cases:
// A) the response is completed, so the parser is in START state;
// B) the content is handled asynchronously, so the parser is in CONTENT state.
return parser.isStart();
return false;
}

protected void fillInterested()
Expand Down Expand Up @@ -244,7 +250,7 @@ public void resume()
{
if (LOG.isDebugEnabled())
LOG.debug("Content consumed asynchronously, resuming processing");
process(getResponseBuffer());
process();
}

public void abort(Throwable x)
Expand Down

0 comments on commit 8cbab09

Please sign in to comment.