killme2008 / xmemcached

High performance, easy to use multithreaded memcached client in java.
http://fnil.net/xmemcached
Apache License 2.0
757 stars 280 forks source link

call dispatch only when stepBuffer returns true #145

Open jcz2 opened 10 months ago

jcz2 commented 10 months ago

Hi, while using the library in one of our projects we noticed a null pointer exception occuring in the XMemcachedClient: https://github.com/killme2008/xmemcached/blob/master/src/main/java/net/rubyeye/xmemcached/XMemcachedClient.java#L1215

java.lang.NullPointerException: null
    at net.rubyeye.xmemcached.XMemcachedClient.reduceResult(XMemcachedClient.java:1215)
    at net.rubyeye.xmemcached.XMemcachedClient.getMulti0(XMemcachedClient.java:1202)
    at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:1088)
    at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:1121)
    at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:1110)

This happens because the TextGetCommand.result is not ready yet when the XMemcachedClient.reduceResult method is invoked.

The result is not ready because a single command may reduce the countdown latch more than once by calling dispatch method inside the TextGetCommand.decode method.

The issue is in this part of the code:

if (first == 'E' && second == 'N') {
  // dispatch result
  dispatch();
  this.currentReturnKey = null;
  // END\r\n
  return ByteUtils.stepBuffer(buffer, 5);
}

It calls dispatch when it encounters E followed by N and returns the result of checking whether the buffer contains 5 or more elements. However if there are less than 5 elements remaining in the buffer then the result will be false and the decode method will be called again, entering the same condition and calling dispatch second time.

To avoid this the pull request changes this part of the code to call dispatch only when there are 5 or more elements in the buffer.