[ 
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: 10.10.1.1
>            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
>  Source:-1)
>           at 
> org.apache.derby.impl.drda.NetworkServerControlImpl.readLDString(Unknown 
> Source:-1)
>           at 
> org.apache.derby.impl.drda.NetworkServerControlImpl.readStringReply(Unknown 
> Source:-1)
>           at 
> org.apache.derby.impl.drda.NetworkServerControlImpl.runtimeInfo(Unknown 
> Source:-1)
>           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
(v6.1.5#6160)

Reply via email to