elasticsearch/elasticsearch — Issue #1494: Infinite loop in DynamicChannelBuffer.ensureWritableBytes
Author: imotov
Created: 2011-11-23 23:16:17+00:00
State: open

Frames larger than 1GB can trigger an infinite loop in [DynamicChannelBuffer.ensureWritableBytes](
https://github.com/netty/netty/blob/3.2/src/main/java/org/jboss/netty/buffer/DynamicChannelBuffer.java#L80). It happens because of integer overflow in newCapacity calculation for any minNewCapacity > 1073741824.

To reproduce:

1) Start ES with enough memory to accomodate 1GB of data.

$ ES_MAX_MEM=2048m bin/elasticsearch -f

2) Execute the following python script

```Python
import socket
import struct

size = 1073741824
chunk = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 9300))
# Send an integer equal to or larger than 1073741824 or large
# so SizeHeaderFrameDecoder would start collecting data
s.send(struct.pack("!l",size))
# followed by at least 1GB of data to trigger overflow
for x in range(size / chunk):
s.send(" " * chunk)
s.close()
```

3) Run jstack on elasticsearch pid

```
$ jstack 5475 | grep -A 20 -B 2 ensureWritableBytes
"New I/O server worker #1-8" daemon prio=5 tid=112092000 nid=0x10d921000 runnable [10d920000]
java.lang.Thread.State: RUNNABLE
at org.elasticsearch.common.netty.buffer.DynamicChannelBuffer.ensureWritableBytes(DynamicChannelBuffer.java:81)
at org.elasticsearch.common.netty.buffer.DynamicChannelBuffer.writeBytes(DynamicChannelBuffer.java:239)
at org.elasticsearch.common.netty.buffer.AbstractChannelBuffer.writeBytes(AbstractChannelBuffer.java:457)
at org.elasticsearch.common.netty.buffer.AbstractChannelBuffer.writeBytes(AbstractChannelBuffer.java:450)
at org.elasticsearch.common.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:213)
at org.elasticsearch.common.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:80)
at org.elasticsearch.common.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
at org.elasticsearch.common.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPipeline.java:783)
at org.elasticsearch.common.netty.OpenChannelsHandler.handleUpstream(OpenChannelsHandler.java:81)
at org.elasticsearch.common.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
at org.elasticsearch.common.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:559)
at org.elasticsearch.common.netty.channel.Channels.fireMessageReceived(Channels.java:274)
at org.elasticsearch.common.netty.channel.Channels.fireMessageReceived(Channels.java:261)
at org.elasticsearch.common.netty.channel.socket.nio.NioWorker.read(NioWorker.java:349)
at org.elasticsearch.common.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:280)
at org.elasticsearch.common.netty.channel.socket.nio.NioWorker.run(NioWorker.java:200)
at org.elasticsearch.common.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.elasticsearch.common.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:44)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
```

This issue was observed on elasticsearch 0.17.7 during shard relocation.