Skip to content

Commit 492dfdd

Browse files
sigurjonviktorssonjoviegaszoewangg
authored
Add null check for channel when generating error message (#3574)
* Add check for channel being null before trying to access properties on it * update changelog * Update NettyUtils.java * Update NettyUtils.java * Update NettyUtils.java * Update NettyUtils.java * Update NettyUtilsTest.java * Update NettyUtilsTest.java * Added CLOSED_CHANNEL_ERROR_MESSAGE to fix compilation issues Co-authored-by: John Viegas <[email protected]> Co-authored-by: Zoe Wang <[email protected]>
1 parent b3b0ef9 commit 492dfdd

File tree

3 files changed

+64
-7
lines changed

3 files changed

+64
-7
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "bugfix",
3+
"category": "AWS SDK for Java v2",
4+
"contributor": "sigurjonviktorsson",
5+
"description": "Prevent NullPointerException in Netty exception handler"
6+
}

http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/utils/NettyUtils.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ public final class NettyUtils {
5353
*/
5454
public static final SucceededFuture<?> SUCCEEDED_FUTURE = new SucceededFuture<>(null, null);
5555

56+
public static final String CLOSED_CHANNEL_ERROR_MESSAGE = "The connection was closed during the request. The request will "
57+
+ "usually succeed on a retry, but if it does not: consider "
58+
+ "disabling any proxies you have configured, enabling debug "
59+
+ "logging, or performing a TCP dump to identify the root cause. "
60+
+ "If this is a streaming operation, validate that data is being "
61+
+ "read or written in a timely manner.";
5662
private static final Logger log = Logger.loggerFor(NettyUtils.class);
5763

5864
private NettyUtils() {
@@ -133,15 +139,14 @@ private static String getMessageForTooManyAcquireOperationsError() {
133139
}
134140

135141
public static String closedChannelMessage(Channel channel) {
136-
ChannelDiagnostics channelDiagnostics = channel.attr(CHANNEL_DIAGNOSTICS).get();
137-
ChannelDiagnostics parentChannelDiagnostics = channel.parent() != null ? channel.parent().attr(CHANNEL_DIAGNOSTICS).get()
138-
: null;
142+
ChannelDiagnostics channelDiagnostics = channel != null && channel.attr(CHANNEL_DIAGNOSTICS) != null ?
143+
channel.attr(CHANNEL_DIAGNOSTICS).get() : null;
144+
ChannelDiagnostics parentChannelDiagnostics = channel != null && channel.parent() != null &&
145+
channel.parent().attr(CHANNEL_DIAGNOSTICS) != null ?
146+
channel.parent().attr(CHANNEL_DIAGNOSTICS).get() : null;
139147

140148
StringBuilder error = new StringBuilder();
141-
error.append("The connection was closed during the request. The request will usually succeed on a retry, but if it does"
142-
+ " not: consider disabling any proxies you have configured, enabling debug logging, or performing a TCP"
143-
+ " dump to identify the root cause. If this is a streaming operation, validate that data is being read or"
144-
+ " written in a timely manner.");
149+
error.append(CLOSED_CHANNEL_ERROR_MESSAGE);
145150

146151
if (channelDiagnostics != null) {
147152
error.append(" Channel Information: ").append(channelDiagnostics);

http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/utils/NettyUtilsTest.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import io.netty.handler.ssl.SslContext;
3030
import io.netty.handler.ssl.SslContextBuilder;
3131
import io.netty.handler.ssl.SslHandler;
32+
import io.netty.util.Attribute;
3233
import io.netty.util.AttributeKey;
3334
import io.netty.util.concurrent.EventExecutor;
3435
import io.netty.util.concurrent.Future;
@@ -41,6 +42,7 @@
4142
import org.junit.jupiter.api.AfterAll;
4243
import org.junit.jupiter.api.BeforeAll;
4344
import org.junit.jupiter.api.Test;
45+
import org.mockito.Mockito;
4446
import org.slf4j.Logger;
4547
import software.amazon.awssdk.http.nio.netty.internal.MockChannel;
4648

@@ -222,4 +224,48 @@ public void runAndLogError_runnableThrows_loggerInvoked() {
222224

223225
verify(delegateLogger).error(msg, error);
224226
}
227+
228+
@Test
229+
public void closedChannelMessage_with_nullChannelAttribute() throws Exception {
230+
231+
Channel channel = Mockito.mock(Channel.class);
232+
when(channel.parent()).thenReturn(null);
233+
234+
assertThat(NettyUtils.closedChannelMessage(channel))
235+
.isEqualTo(NettyUtils.CLOSED_CHANNEL_ERROR_MESSAGE);
236+
}
237+
238+
@Test
239+
public void closedChannelMessage_with_nullChannel() throws Exception {
240+
Channel channel = null;
241+
assertThat(NettyUtils.closedChannelMessage(channel))
242+
.isEqualTo(NettyUtils.CLOSED_CHANNEL_ERROR_MESSAGE);
243+
}
244+
245+
246+
@Test
247+
public void closedChannelMessage_with_nullParentChannel() throws Exception {
248+
249+
Channel channel = mock(Channel.class);
250+
Attribute attribute = mock(Attribute.class);
251+
when(channel.parent()).thenReturn(null);
252+
when(channel.attr(any())).thenReturn(attribute);
253+
254+
assertThat(NettyUtils.closedChannelMessage(channel))
255+
.isEqualTo(NettyUtils.CLOSED_CHANNEL_ERROR_MESSAGE);
256+
}
257+
258+
@Test
259+
public void closedChannelMessage_with_nullParentChannelAttribute() throws Exception {
260+
261+
Channel channel = mock(Channel.class);
262+
Attribute attribute = mock(Attribute.class);
263+
Channel parentChannel = mock(Channel.class);
264+
when(channel.parent()).thenReturn(parentChannel);
265+
when(channel.attr(any())).thenReturn(attribute);
266+
when(parentChannel.attr(any())).thenReturn(null);
267+
268+
assertThat(NettyUtils.closedChannelMessage(channel))
269+
.isEqualTo(NettyUtils.CLOSED_CHANNEL_ERROR_MESSAGE);
270+
}
225271
}

0 commit comments

Comments
 (0)