question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Writing a read-only direct ByteBuffer to channel fails with native transport

See original GitHub issue

Expected behavior

I can take a direct ByteBuffer where isReadOnly() is true, such as the return value of asReadOnlyBuffer() or a MappedBuffer with MapMode.READ_ONLY, pass it to Unpooled.wrappedBuffer(ByteBuffer), and write it to the channel.

Actual behavior

Works with NIO transport. When using kqueue or epoll native transport, writing to the channel fails due to UnsupportedOperationException produced by ReadOnlyByteBufferBuf.memoryAddress().

Minimal yet complete reproducer code

Bootstrap bootstrap = new Bootstrap();
bootstrap.group(new KQueueEventLoopGroup());
bootstrap.channel(KQueueSocketChannel.class);
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ch.pipeline().addLast("HttpResponseDecoder", new HttpResponseDecoder());
        ch.pipeline().addLast("HttpRequestEncoder", new HttpRequestEncoder());
    }
});

final Path path = Paths.get("src/test/resources/upload.txt");
final FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ);

final ByteBuffer dst = ByteBuffer.allocateDirect((int) fileChannel.size());
fileChannel.read(dst, 0);
dst.flip();

bootstrap.connect("httpbin.org", 80).addListener(new ChannelFutureListener() {
    @Override
    public void operationComplete(ChannelFuture future) throws Exception {
        final Channel channel = future.channel();
        DefaultHttpHeaders headers = new DefaultHttpHeaders();
        headers.add("Content-Length", fileChannel.size());
        DefaultHttpRequest req = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/post", headers);
        channel.write(req);
        channel.write(Unpooled.wrappedBuffer(dst.asReadOnlyBuffer()));
        channel.writeAndFlush(DefaultLastHttpContent.EMPTY_LAST_CONTENT).addListener(new GenericFutureListener<Future<? super Void>>() {
            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
                if (!future.isSuccess()) {
                    future.cause().printStackTrace();
                }
            }
        });
    }
});

The above code prints this stack trace when run:

io.netty.channel.socket.ChannelOutputShutdownException: Channel output shutdown
	at io.netty.channel.AbstractChannel$AbstractUnsafe.shutdownOutput(AbstractChannel.java:641)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.flush0(AbstractChannel.java:948)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.flush(AbstractChannel.java:901)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.flush(DefaultChannelPipeline.java:1374)
	at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:776)
	at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:768)
	at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:749)
	at io.netty.channel.ChannelOutboundHandlerAdapter.flush(ChannelOutboundHandlerAdapter.java:115)
	at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:776)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:802)
	at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:814)
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:794)
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:831)
	at io.netty.channel.DefaultChannelPipeline.writeAndFlush(DefaultChannelPipeline.java:1049)
	at io.netty.channel.AbstractChannel.writeAndFlush(AbstractChannel.java:300)
	at test.operationComplete(test)
	at test.operationComplete(test)
	at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:507)
	at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:500)
	at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:479)
	at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:420)
	at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:104)
	at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:84)
	at io.netty.channel.kqueue.AbstractKQueueChannel$AbstractKQueueUnsafe.fulfillConnectPromise(AbstractKQueueChannel.java:593)
	at io.netty.channel.kqueue.AbstractKQueueChannel$AbstractKQueueUnsafe.finishConnect(AbstractKQueueChannel.java:631)
	at io.netty.channel.kqueue.AbstractKQueueChannel$AbstractKQueueUnsafe.writeReady(AbstractKQueueChannel.java:434)
	at io.netty.channel.kqueue.KQueueEventLoop.processReady(KQueueEventLoop.java:192)
	at io.netty.channel.kqueue.KQueueEventLoop.run(KQueueEventLoop.java:269)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.UnsupportedOperationException
	at io.netty.buffer.ReadOnlyByteBufferBuf.memoryAddress(ReadOnlyByteBufferBuf.java:467)
	at io.netty.channel.unix.IovArray.add(IovArray.java:96)
	at io.netty.channel.unix.IovArray.processMessage(IovArray.java:191)
	at io.netty.channel.ChannelOutboundBuffer.forEachFlushedMessage(ChannelOutboundBuffer.java:762)
	at io.netty.channel.kqueue.AbstractKQueueStreamChannel.doWriteMultiple(AbstractKQueueStreamChannel.java:343)
	at io.netty.channel.kqueue.AbstractKQueueStreamChannel.doWrite(AbstractKQueueStreamChannel.java:270)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.flush0(AbstractChannel.java:934)
	... 29 more

Netty version

4.1.20.Final

JVM version (e.g. java -version)

1.8.0_141

OS version (e.g. uname -a)

macOS 10.13.2 (also tried on a recent Ubuntu with epoll transport and got a similar result)

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:8 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
normanmaurercommented, Feb 1, 2018

@RikkiGibson yes please 😃 We love PRs.

1reaction
Scottmitchcommented, Feb 1, 2018

@normanmaurer - https://github.com/netty/netty/commit/7922757575b942d5de5f38d3566857f70b9b4ce6 seems like we missed applying this patch to the duplicate code 😦.

@RikkiGibson - PR sgtm! Make sure you sign the CLA https://netty.io/wiki/developer-guide.html.

Read more comments on GitHub >

github_iconTop Results From Across the Web

ByteBuffer (Java Platform SE 7 ) - Oracle Help Center
A byte buffer is either direct or non-direct. Given a direct byte buffer, the Java virtual machine will make a best effort to...
Read more >
How to write/read the direct ByteBuffer in the native?
1 Answer 1 ... You can read write to FileDescriptors in Java. However to read/write to the direct buffer all you need to...
Read more >
Reliable group communication with JGroups
When true, the ByteBuffer will be created on-heap when unmarshalled, otherwise it will be created off-heap (direct ByteBuffer ).
Read more >
Documentation - Apache Kafka
In Kafka the communication between the clients and the servers is done with a simple, high-performance, language agnostic TCP protocol.
Read more >
Lettuce Reference Guide
Connection and Queue failures now no longer throw an exception but properly ... Native transport support for Kqueue on macOS systems.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found