From a2b85a306df8b02ea2e6f222f56f75355660582b Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Mon, 1 Apr 2019 19:44:28 +0200 Subject: [PATCH] Fix NPE that was encounter by debugger (will never happen in real code). (#8992) Motivation: We synchronize on the chunk.arena when produce the String returned by PoolSubpage.toString() which may raise a NPE when chunk == null. Chunk == null for the head of the linked-list and so a NPE may raised by a debugger. This NPE can never happen in real code tho as we never access toString() of the head. Modifications: Add null checks and so fix the possible NPE Result: No NPE when using a debugger and inspect the PooledByteBufAllocator. --- .../java/io/netty/buffer/PoolSubpage.java | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/buffer/src/main/java/io/netty/buffer/PoolSubpage.java b/buffer/src/main/java/io/netty/buffer/PoolSubpage.java index f897eeeb48..328aae646d 100644 --- a/buffer/src/main/java/io/netty/buffer/PoolSubpage.java +++ b/buffer/src/main/java/io/netty/buffer/PoolSubpage.java @@ -204,16 +204,24 @@ final class PoolSubpage implements PoolSubpageMetric { final int maxNumElems; final int numAvail; final int elemSize; - synchronized (chunk.arena) { - if (!this.doNotDestroy) { - doNotDestroy = false; - // Not used for creating the String. - maxNumElems = numAvail = elemSize = -1; - } else { - doNotDestroy = true; - maxNumElems = this.maxNumElems; - numAvail = this.numAvail; - elemSize = this.elemSize; + if (chunk == null) { + // This is the head so there is no need to synchronize at all as these never change. + doNotDestroy = true; + maxNumElems = 0; + numAvail = 0; + elemSize = -1; + } else { + synchronized (chunk.arena) { + if (!this.doNotDestroy) { + doNotDestroy = false; + // Not used for creating the String. + maxNumElems = numAvail = elemSize = -1; + } else { + doNotDestroy = true; + maxNumElems = this.maxNumElems; + numAvail = this.numAvail; + elemSize = this.elemSize; + } } } @@ -227,6 +235,11 @@ final class PoolSubpage implements PoolSubpageMetric { @Override public int maxNumElements() { + if (chunk == null) { + // It's the head. + return 0; + } + synchronized (chunk.arena) { return maxNumElems; } @@ -234,6 +247,11 @@ final class PoolSubpage implements PoolSubpageMetric { @Override public int numAvailable() { + if (chunk == null) { + // It's the head. + return 0; + } + synchronized (chunk.arena) { return numAvail; } @@ -241,6 +259,11 @@ final class PoolSubpage implements PoolSubpageMetric { @Override public int elementSize() { + if (chunk == null) { + // It's the head. + return -1; + } + synchronized (chunk.arena) { return elemSize; }