db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Knut Anders Hatlen (JIRA)" <j...@apache.org>
Subject [jira] [Updated] (DERBY-6455) Infinite loop in NetworkServerControlImpl.ensureDataInBuffer
Date Mon, 20 Jan 2014 14:29:19 GMT

     [ https://issues.apache.org/jira/browse/DERBY-6455?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel

Knut Anders Hatlen updated DERBY-6455:

    Attachment: d6455-1a.diff

Thanks for the bug report and the patch, Martin.

I'm able to reproduce the problem in my environment by forcing the server to stop sending
data too early. I'm not seeing an infinite loop, but a delay of 15 seconds (at 100% CPU usage)
before the expected error is raised. 15 seconds seems to be the time ensureDataInBuffer()
needs to make replyBufferCount wrap around from Integer.MIN_VALUE to Integer.MAX_VALUE (after
about 2 billion iterations), which makes the loop terminate.

I've reworked the patch a little (see the attached d6455-1a.diff):

1) I made the error checking in ensureDataInBuffer() optional, so that callers that want to
give a more specific error message (such as readCommandReplyHeader()) can still do that.

2) I removed the now redundant checks for insufficient data done by the callers of ensureDataInBuffer().

I didn't add a regression test case for the bug, since it would require changes to the network
server to make it possible to force it to send false data, and also because I wasn't able
to reproduce an infinite loop, only slow completion of the command, so it's difficult to make
the regression test distinguish between the bug and a slow test server.

I've hand-tested the patch against a server that sends truncated data and verified that the
command now fails immediately instead of looping at 100% CPU for a while before failing.

All the regression tests passed with the patch.

> Infinite loop in NetworkServerControlImpl.ensureDataInBuffer
> ------------------------------------------------------------
>                 Key: DERBY-6455
>                 URL: https://issues.apache.org/jira/browse/DERBY-6455
>             Project: Derby
>          Issue Type: Bug
>          Components: Network Server
>    Affects Versions:
>            Reporter: Martin JANDA
>            Priority: Critical
>         Attachments: d6455-1a.diff
> NetworkServerControlImpl.ensureDataInBuffer missing check for return -1 (EOF) from 'clientIs.read'.
When read returns -1 thread consumes 100% CPU. Method NetworkServerControlImpl.fillReplyBuffer
correctly throw exception.
> Fix: add two lines:
>     private void ensureDataInBuffer(int minimumBytesNeeded) throws Exception
>     {
>         // make sure the buffer is large enough
>         while ((replyBufferCount - replyBufferPos) < minimumBytesNeeded)
>         {
>             try {
>                 int bytesRead = clientIs.read(replyBuffer, replyBufferCount, replyBuffer.length
- replyBufferCount);
> +                if (bytesRead == -1)
> +                    consolePropertyMessage("DRDA_InvalidReplyTooShort.S", true);
>                 replyBufferCount += bytesRead;
>             } catch (IOException e)
>             {
>                 clientSocketError(e);
>             }
>         }
>     }
> StackTrace:
>   java.lang.Thread.State: RUNNABLE
>           at java.net.SocketInputStream.read(Unknown Source:-1)
>           at org.apache.derby.impl.drda.NetworkServerControlImpl.ensureDataInBuffer(Unknown
>           at org.apache.derby.impl.drda.NetworkServerControlImpl.readLDString(Unknown
>           at org.apache.derby.impl.drda.NetworkServerControlImpl.readStringReply(Unknown
>           at org.apache.derby.impl.drda.NetworkServerControlImpl.runtimeInfo(Unknown
>           at org.apache.derby.drda.NetworkServerControl.getRuntimeInfo(Unknown Source:-1)
>           at com.crcdata.dbadmin.server.DerbyEngine.getRuntimeInfo(DerbyEngine.java:134)
>           at com.crcdata.dbadmin.server.DerbyEngine$DerbyServerMonitorTask.run(DerbyEngine.java:305)
>           at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source:-1)
>           at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source:-1)
>           at java.util.concurrent.FutureTask.run(Unknown Source:-1)
>           at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source:-1)
>           at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source:-1)
>           at java.lang.Thread.run(Unknown Source:-1)

This message was sent by Atlassian JIRA

View raw message