Set some StackTraceElement on pre-instantiated static exceptions

Motivation:

We use pre-instantiated exceptions in various places for performance reasons. These exceptions don't include a stacktrace which makes it hard to know where the exception was thrown. This is especially true as we use the same exception type (for example ChannelClosedException) in different places. Setting some StackTraceElements will provide more context as to where these exceptions original and make debugging easier.

Modifications:

Set a generated StackTraceElement on these pre-instantiated exceptions which at least contains the origin class and method name. The filename and linenumber are specified as unkown (as stated in the javadocs of StackTraceElement).

Result:

Easier to find the origin of a pre-instantiated exception.
This commit is contained in:
Norman Maurer 2016-06-09 13:29:59 +02:00
parent 16be36a55f
commit e845670043
21 changed files with 258 additions and 196 deletions

View File

@ -34,8 +34,8 @@ import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseDecoder;
import io.netty.handler.codec.http.HttpScheme;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.ThrowableUtil;
import java.net.URI;
import java.nio.channels.ClosedChannelException;
@ -44,11 +44,8 @@ import java.nio.channels.ClosedChannelException;
* Base class for web socket client handshake implementations
*/
public abstract class WebSocketClientHandshaker {
private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException();
static {
CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), WebSocketClientHandshaker.class, "processHandshake(...)");
private final URI uri;

View File

@ -34,6 +34,7 @@ import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.ThrowableUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@ -47,11 +48,8 @@ import java.util.Set;
*/
public abstract class WebSocketServerHandshaker {
protected static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandshaker.class);
private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException();
static {
CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), WebSocketServerHandshaker.class, "handshake(...)");
private final String uri;

View File

@ -20,7 +20,7 @@ import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.ThrowableUtil;
import java.util.concurrent.atomic.AtomicInteger;
@ -32,13 +32,10 @@ import static io.netty.handler.codec.spdy.SpdyCodecUtil.isServerId;
*/
public class SpdySessionHandler extends ChannelDuplexHandler {
private static final SpdyProtocolException PROTOCOL_EXCEPTION = new SpdyProtocolException();
private static final SpdyProtocolException STREAM_CLOSED = new SpdyProtocolException("Stream closed");
static {
PROTOCOL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
STREAM_CLOSED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
private static final SpdyProtocolException PROTOCOL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new SpdyProtocolException(), SpdySessionHandler.class, "handleOutboundMessage(...)");
private static final SpdyProtocolException STREAM_CLOSED = ThrowableUtil.unknownStackTrace(
new SpdyProtocolException("Stream closed"), SpdySessionHandler.class, "removeStream(...)");
private static final int DEFAULT_WINDOW_SIZE = 64 * 1024; // 64 KB default initial window size
private int initialSendWindowSize = DEFAULT_WINDOW_SIZE;

View File

@ -28,7 +28,7 @@ import io.netty.channel.EventLoop;
import io.netty.channel.RecvByteBufAllocator;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.ThrowableUtil;
import java.net.SocketAddress;
import java.nio.channels.ClosedChannelException;
@ -46,17 +46,14 @@ abstract class AbstractHttp2StreamChannel extends AbstractChannel {
*/
protected static final Object CLOSE_MESSAGE = new Object();
private static final ChannelMetadata METADATA = new ChannelMetadata(false, 16);
private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException();
private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), AbstractHttp2StreamChannel.class, "doWrite(...)");
/**
* Number of bytes to consider non-payload messages, to determine when to stop reading. 9 is
* arbitrary, but also the minimum size of an HTTP/2 frame. Primarily is non-zero.
*/
private static final int ARBITRARY_MESSAGE_SIZE = 9;
static {
CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
private final ChannelConfig config = new DefaultChannelConfig(this);
private final Queue<Object> inboundBuffer = new ArrayDeque<Object>(4);
private final Runnable fireChildReadCompleteTask = new Runnable() {

View File

@ -32,7 +32,7 @@
package io.netty.handler.codec.http2.internal.hpack;
import io.netty.handler.codec.http2.internal.hpack.HpackUtil.IndexType;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.ThrowableUtil;
import java.io.IOException;
import java.io.InputStream;
@ -41,21 +41,22 @@ import static io.netty.util.internal.EmptyArrays.EMPTY_BYTES;
public final class Decoder {
private static final IOException DECOMPRESSION_EXCEPTION =
new IOException("HPACK - decompression failure");
private static final IOException ILLEGAL_INDEX_VALUE =
new IOException("HPACK - illegal index value");
private static final IOException INVALID_MAX_DYNAMIC_TABLE_SIZE =
new IOException("HPACK - invalid max dynamic table size");
private static final IOException MAX_DYNAMIC_TABLE_SIZE_CHANGE_REQUIRED =
new IOException("HPACK - max dynamic table size change required");
static {
DECOMPRESSION_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
ILLEGAL_INDEX_VALUE.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
INVALID_MAX_DYNAMIC_TABLE_SIZE.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
MAX_DYNAMIC_TABLE_SIZE_CHANGE_REQUIRED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
private static final IOException DECODE_DECOMPRESSION_EXCEPTION = ThrowableUtil.unknownStackTrace(
new IOException("HPACK - decompression failure"), Decoder.class, "decode(...)");
private static final IOException DECODE_ULE_128_DECOMPRESSION_EXCEPTION = ThrowableUtil.unknownStackTrace(
new IOException("HPACK - decompression failure"), Decoder.class, "decodeULE128(...)");
private static final IOException READ_STRING_LITERAL_DECOMPRESSION_EXCEPTION = ThrowableUtil.unknownStackTrace(
new IOException("HPACK - decompression failure"), Decoder.class, "readStringLiteral(...)");
private static final IOException DECODE_ILLEGAL_INDEX_VALUE = ThrowableUtil.unknownStackTrace(
new IOException("HPACK - illegal index value"), Decoder.class, "decode(...)");
private static final IOException INDEX_HEADER_ILLEGAL_INDEX_VALUE = ThrowableUtil.unknownStackTrace(
new IOException("HPACK - illegal index value"), Decoder.class, "indexHeader(...)");
private static final IOException READ_NAME_ILLEGAL_INDEX_VALUE = ThrowableUtil.unknownStackTrace(
new IOException("HPACK - illegal index value"), Decoder.class, "readName(...)");
private static final IOException INVALID_MAX_DYNAMIC_TABLE_SIZE = ThrowableUtil.unknownStackTrace(
new IOException("HPACK - invalid max dynamic table size"), Decoder.class, "setDynamicTableSize(...)");
private static final IOException MAX_DYNAMIC_TABLE_SIZE_CHANGE_REQUIRED = ThrowableUtil.unknownStackTrace(
new IOException("HPACK - max dynamic table size change required"), Decoder.class, "decode(...)");
private final DynamicTable dynamicTable;
@ -123,7 +124,7 @@ public final class Decoder {
// Indexed Header Field
index = b & 0x7F;
if (index == 0) {
throw ILLEGAL_INDEX_VALUE;
throw DECODE_ILLEGAL_INDEX_VALUE;
} else if (index == 0x7F) {
state = State.READ_INDEXED_HEADER;
} else {
@ -175,7 +176,7 @@ public final class Decoder {
// Check for numerical overflow
if (maxSize > Integer.MAX_VALUE - index) {
throw DECOMPRESSION_EXCEPTION;
throw DECODE_DECOMPRESSION_EXCEPTION;
}
setDynamicTableSize(index + maxSize);
@ -190,7 +191,7 @@ public final class Decoder {
// Check for numerical overflow
if (headerIndex > Integer.MAX_VALUE - index) {
throw DECOMPRESSION_EXCEPTION;
throw DECODE_DECOMPRESSION_EXCEPTION;
}
indexHeader(index + headerIndex, headerListener);
@ -206,7 +207,7 @@ public final class Decoder {
// Check for numerical overflow
if (nameIndex > Integer.MAX_VALUE - index) {
throw DECOMPRESSION_EXCEPTION;
throw DECODE_DECOMPRESSION_EXCEPTION;
}
readName(index + nameIndex);
@ -255,7 +256,7 @@ public final class Decoder {
// Check for numerical overflow
if (nameLength > Integer.MAX_VALUE - index) {
throw DECOMPRESSION_EXCEPTION;
throw DECODE_DECOMPRESSION_EXCEPTION;
}
nameLength += index;
@ -348,7 +349,7 @@ public final class Decoder {
// Check for numerical overflow
if (valueLength > Integer.MAX_VALUE - index) {
throw DECOMPRESSION_EXCEPTION;
throw DECODE_DECOMPRESSION_EXCEPTION;
}
valueLength += index;
@ -469,7 +470,7 @@ public final class Decoder {
HeaderField headerField = dynamicTable.getEntry(index - StaticTable.length);
name = headerField.name;
} else {
throw ILLEGAL_INDEX_VALUE;
throw READ_NAME_ILLEGAL_INDEX_VALUE;
}
}
@ -481,7 +482,7 @@ public final class Decoder {
HeaderField headerField = dynamicTable.getEntry(index - StaticTable.length);
addHeader(headerListener, headerField.name, headerField.value, false);
} else {
throw ILLEGAL_INDEX_VALUE;
throw INDEX_HEADER_ILLEGAL_INDEX_VALUE;
}
}
@ -529,7 +530,7 @@ public final class Decoder {
private byte[] readStringLiteral(InputStream in, int length) throws IOException {
byte[] buf = new byte[length];
if (in.read(buf) != length) {
throw DECOMPRESSION_EXCEPTION;
throw READ_STRING_LITERAL_DECOMPRESSION_EXCEPTION;
}
if (huffmanEncoded) {
@ -563,6 +564,6 @@ public final class Decoder {
}
// Value exceeds Integer.MAX_VALUE
in.reset();
throw DECOMPRESSION_EXCEPTION;
throw DECODE_ULE_128_DECOMPRESSION_EXCEPTION;
}
}

View File

@ -31,20 +31,17 @@
*/
package io.netty.handler.codec.http2.internal.hpack;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.ThrowableUtil;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
final class HuffmanDecoder {
private static final IOException EOS_DECODED = new IOException("HPACK - EOS Decoded");
private static final IOException INVALID_PADDING = new IOException("HPACK - Invalid Padding");
static {
EOS_DECODED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
INVALID_PADDING.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
private static final IOException EOS_DECODED = ThrowableUtil.unknownStackTrace(
new IOException("HPACK - EOS Decoded"), HuffmanDecoder.class, "decode(...)");
private static final IOException INVALID_PADDING = ThrowableUtil.unknownStackTrace(
new IOException("HPACK - Invalid Padding"), HuffmanDecoder.class, "decode(...)");
private final Node root;

View File

@ -16,10 +16,10 @@
package io.netty.util.concurrent;
import io.netty.util.Signal;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.InternalThreadLocalMap;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.ThrowableUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@ -39,7 +39,8 @@ public class DefaultPromise<V> extends AbstractFuture<V> implements Promise<V> {
private static final AtomicReferenceFieldUpdater<DefaultPromise, Object> RESULT_UPDATER;
private static final Signal SUCCESS = Signal.valueOf(DefaultPromise.class, "SUCCESS");
private static final Signal UNCANCELLABLE = Signal.valueOf(DefaultPromise.class, "UNCANCELLABLE");
private static final CauseHolder CANCELLATION_CAUSE_HOLDER = new CauseHolder(new CancellationException());
private static final CauseHolder CANCELLATION_CAUSE_HOLDER = new CauseHolder(ThrowableUtil.unknownStackTrace(
new CancellationException(), DefaultPromise.class, "cancel(...)"));
static {
@SuppressWarnings("rawtypes")
@ -47,7 +48,6 @@ public class DefaultPromise<V> extends AbstractFuture<V> implements Promise<V> {
PlatformDependent.newAtomicReferenceFieldUpdater(DefaultPromise.class, "result");
RESULT_UPDATER = updater == null ? AtomicReferenceFieldUpdater.newUpdater(DefaultPromise.class,
Object.class, "result") : updater;
CANCELLATION_CAUSE_HOLDER.cause.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
private volatile Object result;

View File

@ -0,0 +1,29 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.util.internal;
public final class ThrowableUtil {
private ThrowableUtil() { }
/**
* Set the {@link StackTraceElement} for the given {@link Throwable}, using the {@link Class} and method name.
*/
public static <T extends Throwable> T unknownStackTrace(T cause, Class<?> clazz, String method) {
cause.setStackTrace(new StackTraceElement[] { new StackTraceElement(clazz.getName(), method, null, -1)});
return cause;
}
}

View File

@ -22,6 +22,7 @@ import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.InternalThreadLocalMap;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.ThrowableUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import org.apache.tomcat.jni.Buffer;
@ -78,9 +79,14 @@ public final class OpenSslEngine extends SSLEngine {
private static final Certificate[] EMPTY_CERTIFICATES = EmptyArrays.EMPTY_CERTIFICATES;
private static final X509Certificate[] EMPTY_X509_CERTIFICATES = EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
private static final SSLException ENGINE_CLOSED = new SSLException("engine closed");
private static final SSLException RENEGOTIATION_UNSUPPORTED = new SSLException("renegotiation unsupported");
private static final SSLException ENCRYPTED_PACKET_OVERSIZED = new SSLException("encrypted packet oversized");
private static final SSLException BEGIN_HANDSHAKE_ENGINE_CLOSED = ThrowableUtil.unknownStackTrace(
new SSLException("engine closed"), OpenSslEngine.class, "beginHandshake()");
private static final SSLException HANDSHAKE_ENGINE_CLOSED = ThrowableUtil.unknownStackTrace(
new SSLException("engine closed"), OpenSslEngine.class, "handshake()");
private static final SSLException RENEGOTIATION_UNSUPPORTED = ThrowableUtil.unknownStackTrace(
new SSLException("renegotiation unsupported"), OpenSslEngine.class, "beginHandshake()");
private static final SSLException ENCRYPTED_PACKET_OVERSIZED = ThrowableUtil.unknownStackTrace(
new SSLException("encrypted packet oversized"), OpenSslEngine.class, "unwrap(...)");
private static final Class<?> SNI_HOSTNAME_CLASS;
private static final Method GET_SERVER_NAMES_METHOD;
private static final Method SET_SERVER_NAMES_METHOD;
@ -89,10 +95,6 @@ public final class OpenSslEngine extends SSLEngine {
private static final Method SET_USE_CIPHER_SUITES_ORDER_METHOD;
static {
ENGINE_CLOSED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
RENEGOTIATION_UNSUPPORTED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
ENCRYPTED_PACKET_OVERSIZED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
AtomicIntegerFieldUpdater<OpenSslEngine> destroyedUpdater =
PlatformDependent.newAtomicIntegerFieldUpdater(OpenSslEngine.class, "destroyed");
if (destroyedUpdater == null) {
@ -1208,7 +1210,7 @@ public final class OpenSslEngine extends SSLEngine {
public synchronized void beginHandshake() throws SSLException {
switch (handshakeState) {
case STARTED_IMPLICITLY:
checkEngineClosed();
checkEngineClosed(BEGIN_HANDSHAKE_ENGINE_CLOSED);
// A user did not start handshake by calling this method by him/herself,
// but handshake has been started already by wrap() or unwrap() implicitly.
@ -1255,9 +1257,9 @@ public final class OpenSslEngine extends SSLEngine {
}
}
private void checkEngineClosed() throws SSLException {
private void checkEngineClosed(SSLException cause) throws SSLException {
if (engineClosed || isDestroyed()) {
throw ENGINE_CLOSED;
throw cause;
}
}
@ -1270,7 +1272,7 @@ public final class OpenSslEngine extends SSLEngine {
if (handshakeState == HandshakeState.FINISHED) {
return FINISHED;
}
checkEngineClosed();
checkEngineClosed(HANDSHAKE_ENGINE_CLOSED);
// Check if we have a pending handshakeException and if so see if we need to consume all pending data from the
// BIO first or can just shutdown and throw it now.

View File

@ -40,8 +40,8 @@ import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener;
import io.netty.util.concurrent.ImmediateExecutor;
import io.netty.util.concurrent.Promise;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.ThrowableUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@ -177,15 +177,12 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
* {@link #unwrap(ChannelHandlerContext, ByteBuf, int, int)}. Using this static instance reduce object
* creation as {@link Unpooled#EMPTY_BUFFER#nioBuffer()} creates a new {@link ByteBuffer} everytime.
*/
private static final SSLException SSLENGINE_CLOSED = new SSLException("SSLEngine closed already");
private static final SSLException HANDSHAKE_TIMED_OUT = new SSLException("handshake timed out");
private static final ClosedChannelException CHANNEL_CLOSED = new ClosedChannelException();
static {
SSLENGINE_CLOSED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
HANDSHAKE_TIMED_OUT.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
CHANNEL_CLOSED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
private static final SSLException SSLENGINE_CLOSED = ThrowableUtil.unknownStackTrace(
new SSLException("SSLEngine closed already"), SslHandler.class, "wrap(...)");
private static final SSLException HANDSHAKE_TIMED_OUT = ThrowableUtil.unknownStackTrace(
new SSLException("handshake timed out"), SslHandler.class, "handshake(...)");
private static final ClosedChannelException CHANNEL_CLOSED = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), SslHandler.class, "channelInactive(...)");
private volatile ChannelHandlerContext ctx;
private final SSLEngine engine;

View File

@ -32,9 +32,9 @@ import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.socket.DuplexChannel;
import io.netty.channel.unix.FileDescriptor;
import io.netty.channel.unix.Socket;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.ThrowableUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@ -56,11 +56,17 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im
" (expected: " + StringUtil.simpleClassName(ByteBuf.class) + ", " +
StringUtil.simpleClassName(DefaultFileRegion.class) + ')';
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractEpollStreamChannel.class);
static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException();
static {
CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
private static final ClosedChannelException DO_CLOSE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), AbstractEpollStreamChannel.class, "doClose()");
private static final ClosedChannelException CLEAR_SPLICE_QUEUE_CLOSED_CHANNEL_EXCEPTION =
ThrowableUtil.unknownStackTrace(new ClosedChannelException(),
AbstractEpollStreamChannel.class, "clearSpliceQueue()");
private static final ClosedChannelException SPLICE_TO_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(),
AbstractEpollStreamChannel.class, "spliceTo(...)");
private static final ClosedChannelException FAIL_SPLICE_IF_CLOSED_CLOSED_CHANNEL_EXCEPTION =
ThrowableUtil.unknownStackTrace(new ClosedChannelException(),
AbstractEpollStreamChannel.class, "failSpliceIfClosed(...)");
/**
* The future of the current connection attempt. If not null, subsequent
@ -170,7 +176,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im
}
checkNotNull(promise, "promise");
if (!isOpen()) {
promise.tryFailure(CLOSED_CHANNEL_EXCEPTION);
promise.tryFailure(SPLICE_TO_CLOSED_CHANNEL_EXCEPTION);
} else {
addToSpliceQueue(new SpliceInChannelTask(ch, len, promise));
failSpliceIfClosed(promise);
@ -223,7 +229,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im
}
checkNotNull(promise, "promise");
if (!isOpen()) {
promise.tryFailure(CLOSED_CHANNEL_EXCEPTION);
promise.tryFailure(SPLICE_TO_CLOSED_CHANNEL_EXCEPTION);
} else {
addToSpliceQueue(new SpliceFdTask(ch, offset, len, promise));
failSpliceIfClosed(promise);
@ -235,7 +241,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im
if (!isOpen()) {
// Seems like the Channel was closed in the meantime try to fail the promise to prevent any
// cases where a future may not be notified otherwise.
if (promise.tryFailure(CLOSED_CHANNEL_EXCEPTION)) {
if (promise.tryFailure(FAIL_SPLICE_IF_CLOSED_CLOSED_CHANNEL_EXCEPTION)) {
eventLoop().execute(new Runnable() {
@Override
public void run() {
@ -669,7 +675,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im
ChannelPromise promise = connectPromise;
if (promise != null) {
// Use tryFailure() instead of setFailure() to avoid the race against cancel().
promise.tryFailure(CLOSED_CHANNEL_EXCEPTION);
promise.tryFailure(DO_CLOSE_CLOSED_CHANNEL_EXCEPTION);
connectPromise = null;
}
@ -696,7 +702,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im
if (task == null) {
break;
}
task.promise.tryFailure(CLOSED_CHANNEL_EXCEPTION);
task.promise.tryFailure(CLEAR_SPLICE_QUEUE_CLOSED_CHANNEL_EXCEPTION);
}
}

View File

@ -22,9 +22,11 @@ import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.SystemPropertyUtil;
import io.netty.channel.unix.FileDescriptor;
import io.netty.channel.unix.NativeInetAddress;
import io.netty.util.internal.ThrowableUtil;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.channels.ClosedChannelException;
import java.util.Locale;
import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.epollerr;
@ -78,16 +80,22 @@ public final class Native {
public static final int TCP_MD5SIG_MAXKEYLEN = tcpMd5SigMaxKeyLen();
public static final String KERNEL_VERSION = kernelVersion();
private static final NativeIoException CONNECTION_RESET_EXCEPTION_SENDFILE;
private static final NativeIoException CONNECTION_RESET_EXCEPTION_SENDMMSG;
private static final NativeIoException CONNECTION_RESET_EXCEPTION_SPLICE;
private static final NativeIoException SENDFILE_CONNECTION_RESET_EXCEPTION;
private static final NativeIoException SENDMMSG_CONNECTION_RESET_EXCEPTION;
private static final NativeIoException SPLICE_CONNECTION_RESET_EXCEPTION;
private static final ClosedChannelException SENDFILE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), Native.class, "sendfile(...)");
private static final ClosedChannelException SENDMMSG_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), Native.class, "sendmmsg(...)");
private static final ClosedChannelException SPLICE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), Native.class, "splice(...)");
static {
CONNECTION_RESET_EXCEPTION_SENDFILE = newConnectionResetException("syscall:sendfile(...)",
SENDFILE_CONNECTION_RESET_EXCEPTION = newConnectionResetException("syscall:sendfile(...)",
ERRNO_EPIPE_NEGATIVE);
CONNECTION_RESET_EXCEPTION_SENDMMSG = newConnectionResetException("syscall:sendmmsg(...)",
SENDMMSG_CONNECTION_RESET_EXCEPTION = newConnectionResetException("syscall:sendmmsg(...)",
ERRNO_EPIPE_NEGATIVE);
CONNECTION_RESET_EXCEPTION_SPLICE = newConnectionResetException("syscall:splice(...)",
SPLICE_CONNECTION_RESET_EXCEPTION = newConnectionResetException("syscall:splice(...)",
ERRNO_EPIPE_NEGATIVE);
}
@ -144,7 +152,7 @@ public final class Native {
if (res >= 0) {
return res;
}
return ioResult("splice", res, CONNECTION_RESET_EXCEPTION_SPLICE);
return ioResult("splice", res, SPLICE_CONNECTION_RESET_EXCEPTION, SPLICE_CLOSED_CHANNEL_EXCEPTION);
}
private static native int splice0(int fd, long offIn, int fdOut, long offOut, long len);
@ -159,7 +167,7 @@ public final class Native {
if (res >= 0) {
return res;
}
return ioResult("sendfile", (int) res, CONNECTION_RESET_EXCEPTION_SENDFILE);
return ioResult("sendfile", (int) res, SENDFILE_CONNECTION_RESET_EXCEPTION, SENDFILE_CLOSED_CHANNEL_EXCEPTION);
}
private static native long sendfile0(
@ -171,7 +179,7 @@ public final class Native {
if (res >= 0) {
return res;
}
return ioResult("sendmmsg", res, CONNECTION_RESET_EXCEPTION_SENDMMSG);
return ioResult("sendmmsg", res, SENDMMSG_CONNECTION_RESET_EXCEPTION, SENDMMSG_CLOSED_CHANNEL_EXCEPTION);
}
private static native int sendmmsg0(

View File

@ -53,16 +53,6 @@ public final class Errors {
*/
private static final String[] ERRORS = new String[512];
// Pre-instantiated exceptions which does not need any stacktrace and
// can be thrown multiple times for performance reasons.
static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION;
static final NativeIoException CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION;
static final NativeIoException CONNECTION_RESET_EXCEPTION_WRITE;
static final NativeIoException CONNECTION_RESET_EXCEPTION_WRITEV;
static final NativeIoException CONNECTION_RESET_EXCEPTION_READ;
static final NativeIoException CONNECTION_RESET_EXCEPTION_SENDTO;
static final NativeIoException CONNECTION_RESET_EXCEPTION_SENDMSG;
/**
* <strong>Internal usage only!</strong>
*/
@ -84,21 +74,6 @@ public final class Errors {
// This is ok as strerror returns 'Unknown error i' when the message is not known.
ERRORS[i] = strError(i);
}
CONNECTION_RESET_EXCEPTION_READ = newConnectionResetException("syscall:read(...)",
ERRNO_ECONNRESET_NEGATIVE);
CONNECTION_RESET_EXCEPTION_WRITE = newConnectionResetException("syscall:write(...)",
ERRNO_EPIPE_NEGATIVE);
CONNECTION_RESET_EXCEPTION_WRITEV = newConnectionResetException("syscall:writev(...)",
ERRNO_EPIPE_NEGATIVE);
CONNECTION_RESET_EXCEPTION_SENDTO = newConnectionResetException("syscall:sendto(...)",
ERRNO_EPIPE_NEGATIVE);
CONNECTION_RESET_EXCEPTION_SENDMSG = newConnectionResetException("syscall:sendmsg(...)",
ERRNO_EPIPE_NEGATIVE);
CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION = newConnectionResetException("syscall:shutdown(...)",
ERRNO_ENOTCONN_NEGATIVE);
CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException();
CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
static ConnectException newConnectException(String method, int err) {
@ -115,7 +90,8 @@ public final class Errors {
return new NativeIoException(method + "() failed: " + ERRORS[-err], err);
}
public static int ioResult(String method, int err, NativeIoException resetCause) throws IOException {
public static int ioResult(String method, int err, NativeIoException resetCause,
ClosedChannelException closedCause) throws IOException {
// network stack saturated... try again later
if (err == ERRNO_EAGAIN_NEGATIVE || err == ERRNO_EWOULDBLOCK_NEGATIVE) {
return 0;
@ -124,7 +100,7 @@ public final class Errors {
throw resetCause;
}
if (err == ERRNO_EBADF_NEGATIVE || err == ERRNO_ENOTCONN_NEGATIVE) {
throw CLOSED_CHANNEL_EXCEPTION;
throw closedCause;
}
// TODO: We could even go further and use a pre-instantiated IOException for the other error codes, but for
// all other errors it may be better to just include a stack trace.

View File

@ -16,15 +16,14 @@
package io.netty.channel.unix;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.ThrowableUtil;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import static io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_READ;
import static io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_WRITE;
import static io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_WRITEV;
import static io.netty.channel.unix.Errors.ioResult;
import static io.netty.channel.unix.Errors.newIOException;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
@ -34,6 +33,37 @@ import static io.netty.util.internal.ObjectUtil.checkNotNull;
* {@link FileDescriptor} for it.
*/
public class FileDescriptor {
private static final ClosedChannelException WRITE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), FileDescriptor.class, "write(...)");
private static final ClosedChannelException WRITE_ADDRESS_CLOSED_CHANNEL_EXCEPTION =
ThrowableUtil.unknownStackTrace(new ClosedChannelException(), FileDescriptor.class, "writeAddress(...)");
private static final ClosedChannelException WRITEV_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), FileDescriptor.class, "writev(...)");
private static final ClosedChannelException WRITEV_ADDRESSES_CLOSED_CHANNEL_EXCEPTION =
ThrowableUtil.unknownStackTrace(new ClosedChannelException(), FileDescriptor.class, "writevAddresses(...)");
private static final ClosedChannelException READ_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), FileDescriptor.class, "read(...)");
private static final ClosedChannelException READ_ADDRESS_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), FileDescriptor.class, "readAddress(...)");
private static final Errors.NativeIoException WRITE_CONNECTION_RESET_EXCEPTION = ThrowableUtil.unknownStackTrace(
Errors.newConnectionResetException("syscall:write(...)", Errors.ERRNO_EPIPE_NEGATIVE),
FileDescriptor.class, "write(...)");
private static final Errors.NativeIoException WRITE_ADDRESS_CONNECTION_RESET_EXCEPTION =
ThrowableUtil.unknownStackTrace(Errors.newConnectionResetException("syscall:write(...)",
Errors.ERRNO_EPIPE_NEGATIVE), FileDescriptor.class, "writeAddress(...)");
private static final Errors.NativeIoException WRITEV_CONNECTION_RESET_EXCEPTION = ThrowableUtil.unknownStackTrace(
Errors.newConnectionResetException("syscall:writev(...)", Errors.ERRNO_EPIPE_NEGATIVE),
FileDescriptor.class, "writev(...)");
private static final Errors.NativeIoException WRITEV_ADDRESSES_CONNECTION_RESET_EXCEPTION =
ThrowableUtil.unknownStackTrace(Errors.newConnectionResetException("syscall:writev(...)",
Errors.ERRNO_EPIPE_NEGATIVE), FileDescriptor.class, "writeAddresses(...)");
private static final Errors.NativeIoException READ_CONNECTION_RESET_EXCEPTION = ThrowableUtil.unknownStackTrace(
Errors.newConnectionResetException("syscall:read(...)", Errors.ERRNO_ECONNRESET_NEGATIVE),
FileDescriptor.class, "read(...)");
private static final Errors.NativeIoException READ_ADDRESS_CONNECTION_RESET_EXCEPTION =
ThrowableUtil.unknownStackTrace(Errors.newConnectionResetException("syscall:read(...)",
Errors.ERRNO_ECONNRESET_NEGATIVE), FileDescriptor.class, "readAddress(...)");
private static final AtomicIntegerFieldUpdater<FileDescriptor> stateUpdater;
static {
AtomicIntegerFieldUpdater<FileDescriptor> updater
@ -43,6 +73,7 @@ public class FileDescriptor {
}
stateUpdater = updater;
}
private static final int STATE_CLOSED_MASK = 1;
private static final int STATE_INPUT_SHUTDOWN_MASK = 1 << 1;
private static final int STATE_OUTPUT_SHUTDOWN_MASK = 1 << 2;
@ -101,7 +132,7 @@ public class FileDescriptor {
if (res >= 0) {
return res;
}
return ioResult("write", res, CONNECTION_RESET_EXCEPTION_WRITE);
return ioResult("write", res, WRITE_CONNECTION_RESET_EXCEPTION, WRITE_CLOSED_CHANNEL_EXCEPTION);
}
public final int writeAddress(long address, int pos, int limit) throws IOException {
@ -109,7 +140,8 @@ public class FileDescriptor {
if (res >= 0) {
return res;
}
return ioResult("writeAddress", res, CONNECTION_RESET_EXCEPTION_WRITE);
return ioResult("writeAddress", res,
WRITE_ADDRESS_CONNECTION_RESET_EXCEPTION, WRITE_ADDRESS_CLOSED_CHANNEL_EXCEPTION);
}
public final long writev(ByteBuffer[] buffers, int offset, int length) throws IOException {
@ -117,7 +149,7 @@ public class FileDescriptor {
if (res >= 0) {
return res;
}
return ioResult("writev", (int) res, CONNECTION_RESET_EXCEPTION_WRITEV);
return ioResult("writev", (int) res, WRITEV_CONNECTION_RESET_EXCEPTION, WRITEV_CLOSED_CHANNEL_EXCEPTION);
}
public final long writevAddresses(long memoryAddress, int length) throws IOException {
@ -125,7 +157,8 @@ public class FileDescriptor {
if (res >= 0) {
return res;
}
return ioResult("writevAddresses", (int) res, CONNECTION_RESET_EXCEPTION_WRITEV);
return ioResult("writevAddresses", (int) res,
WRITEV_ADDRESSES_CONNECTION_RESET_EXCEPTION, WRITEV_ADDRESSES_CLOSED_CHANNEL_EXCEPTION);
}
public final int read(ByteBuffer buf, int pos, int limit) throws IOException {
@ -136,7 +169,7 @@ public class FileDescriptor {
if (res == 0) {
return -1;
}
return ioResult("read", res, CONNECTION_RESET_EXCEPTION_READ);
return ioResult("read", res, READ_CONNECTION_RESET_EXCEPTION, READ_CLOSED_CHANNEL_EXCEPTION);
}
public final int readAddress(long address, int pos, int limit) throws IOException {
@ -147,7 +180,8 @@ public class FileDescriptor {
if (res == 0) {
return -1;
}
return ioResult("readAddress", res, CONNECTION_RESET_EXCEPTION_READ);
return ioResult("readAddress", res,
READ_ADDRESS_CONNECTION_RESET_EXCEPTION, READ_ADDRESS_CLOSED_CHANNEL_EXCEPTION);
}
@Override

View File

@ -17,6 +17,7 @@ package io.netty.channel.unix;
import io.netty.channel.ChannelException;
import io.netty.util.CharsetUtil;
import io.netty.util.internal.ThrowableUtil;
import java.io.IOException;
import java.net.Inet6Address;
@ -24,10 +25,8 @@ import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import static io.netty.channel.unix.Errors.CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION;
import static io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_SENDMSG;
import static io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_SENDTO;
import static io.netty.channel.unix.Errors.ERRNO_EAGAIN_NEGATIVE;
import static io.netty.channel.unix.Errors.ERRNO_EINPROGRESS_NEGATIVE;
import static io.netty.channel.unix.Errors.ERRNO_EWOULDBLOCK_NEGATIVE;
@ -42,6 +41,26 @@ import static io.netty.channel.unix.NativeInetAddress.ipv4MappedIpv6Address;
* <strong>Internal usage only!</strong>
*/
public final class Socket extends FileDescriptor {
private static final ClosedChannelException SHUTDOWN_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), Socket.class, "shutdown(...)");
private static final ClosedChannelException SEND_TO_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), Socket.class, "sendTo(...)");
private static final ClosedChannelException SEND_TO_ADDRESS_CLOSED_CHANNEL_EXCEPTION =
ThrowableUtil.unknownStackTrace(new ClosedChannelException(), Socket.class, "sendToAddress(...)");
private static final ClosedChannelException SEND_TO_ADDRESSES_CLOSED_CHANNEL_EXCEPTION =
ThrowableUtil.unknownStackTrace(new ClosedChannelException(), Socket.class, "sendToAddresses(...)");
private static final Errors.NativeIoException SEND_TO_CONNECTION_RESET_EXCEPTION = ThrowableUtil.unknownStackTrace(
Errors.newConnectionResetException("syscall:sendto(...)", Errors.ERRNO_EPIPE_NEGATIVE),
Socket.class, "sendTo(...)");
private static final Errors.NativeIoException SEND_TO_ADDRESS_CONNECTION_RESET_EXCEPTION =
ThrowableUtil.unknownStackTrace(Errors.newConnectionResetException("syscall:sendto(...)",
Errors.ERRNO_EPIPE_NEGATIVE), Socket.class, "sendToAddress(...)");
private static final Errors.NativeIoException CONNECTION_RESET_EXCEPTION_SENDMSG = ThrowableUtil.unknownStackTrace(
Errors.newConnectionResetException("syscall:sendmsg(...)",
Errors.ERRNO_EPIPE_NEGATIVE), Socket.class, "sendToAddresses(...)");
private static final Errors.NativeIoException CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION =
ThrowableUtil.unknownStackTrace(Errors.newConnectionResetException("syscall:shutdown(...)",
Errors.ERRNO_ENOTCONN_NEGATIVE), Socket.class, "shutdown(...)");
public Socket(int fd) {
super(fd);
}
@ -75,7 +94,7 @@ public final class Socket extends FileDescriptor {
}
int res = shutdown(fd, read, write);
if (res < 0) {
ioResult("shutdown", res, CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION);
ioResult("shutdown", res, CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION, SHUTDOWN_CLOSED_CHANNEL_EXCEPTION);
}
}
@ -109,7 +128,7 @@ public final class Socket extends FileDescriptor {
if (res >= 0) {
return res;
}
return ioResult("sendTo", res, CONNECTION_RESET_EXCEPTION_SENDTO);
return ioResult("sendTo", res, SEND_TO_CONNECTION_RESET_EXCEPTION, SEND_TO_CLOSED_CHANNEL_EXCEPTION);
}
public int sendToAddress(long memoryAddress, int pos, int limit, InetAddress addr, int port)
@ -130,7 +149,8 @@ public final class Socket extends FileDescriptor {
if (res >= 0) {
return res;
}
return ioResult("sendToAddress", res, CONNECTION_RESET_EXCEPTION_SENDTO);
return ioResult("sendToAddress", res,
SEND_TO_ADDRESS_CONNECTION_RESET_EXCEPTION, SEND_TO_ADDRESS_CLOSED_CHANNEL_EXCEPTION);
}
public int sendToAddresses(long memoryAddress, int length, InetAddress addr, int port) throws IOException {
@ -150,7 +170,8 @@ public final class Socket extends FileDescriptor {
if (res >= 0) {
return res;
}
return ioResult("sendToAddresses", res, CONNECTION_RESET_EXCEPTION_SENDMSG);
return ioResult("sendToAddresses", res,
CONNECTION_RESET_EXCEPTION_SENDMSG, SEND_TO_ADDRESSES_CLOSED_CHANNEL_EXCEPTION);
}
public DatagramSocketAddress recvFrom(ByteBuffer buf, int pos, int limit) throws IOException {

View File

@ -18,8 +18,8 @@ package io.netty.channel;
import io.netty.buffer.ByteBufAllocator;
import io.netty.util.DefaultAttributeMap;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.ThrowableUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@ -41,13 +41,16 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractChannel.class);
static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException();
static final NotYetConnectedException NOT_YET_CONNECTED_EXCEPTION = new NotYetConnectedException();
static {
CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
NOT_YET_CONNECTED_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
private static final ClosedChannelException FLUSH0_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), AbstractUnsafe.class, "flush0()");
private static final ClosedChannelException ENSURE_OPEN_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), AbstractUnsafe.class, "ensureOpen(...)");
private static final ClosedChannelException CLOSE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), AbstractUnsafe.class, "close(...)");
private static final ClosedChannelException WRITE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), AbstractUnsafe.class, "write(...)");
private static final NotYetConnectedException FLUSH0_NOT_YET_CONNECTED_EXCEPTION = ThrowableUtil.unknownStackTrace(
new NotYetConnectedException(), AbstractUnsafe.class, "flush0()");
private final Channel parent;
private final ChannelId id;
@ -592,10 +595,11 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
public final void close(final ChannelPromise promise) {
assertEventLoop();
close(promise, CLOSED_CHANNEL_EXCEPTION, false);
close(promise, CLOSE_CLOSED_CHANNEL_EXCEPTION, CLOSE_CLOSED_CHANNEL_EXCEPTION, false);
}
private void close(final ChannelPromise promise, final Throwable cause, final boolean notify) {
private void close(final ChannelPromise promise, final Throwable cause,
final ClosedChannelException closeCause, final boolean notify) {
if (!promise.setUncancellable()) {
return;
}
@ -638,7 +642,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
public void run() {
// Fail all the queued messages
outboundBuffer.failFlushed(cause, notify);
outboundBuffer.close(CLOSED_CHANNEL_EXCEPTION);
outboundBuffer.close(closeCause);
fireChannelInactiveAndDeregister(wasActive);
}
});
@ -652,7 +656,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
} finally {
// Fail all the queued messages.
outboundBuffer.failFlushed(cause, notify);
outboundBuffer.close(CLOSED_CHANNEL_EXCEPTION);
outboundBuffer.close(closeCause);
}
if (inFlush0) {
invokeLater(new Runnable() {
@ -775,7 +779,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
// need to fail the future right away. If it is not null the handling of the rest
// will be done in flush0()
// See https://github.com/netty/netty/issues/2362
safeSetFailure(promise, CLOSED_CHANNEL_EXCEPTION);
safeSetFailure(promise, WRITE_CLOSED_CHANNEL_EXCEPTION);
// release message now to prevent resource-leak
ReferenceCountUtil.release(msg);
return;
@ -828,10 +832,10 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
if (!isActive()) {
try {
if (isOpen()) {
outboundBuffer.failFlushed(NOT_YET_CONNECTED_EXCEPTION, true);
outboundBuffer.failFlushed(FLUSH0_NOT_YET_CONNECTED_EXCEPTION, true);
} else {
// Do not trigger channelWritabilityChanged because the channel is closed already.
outboundBuffer.failFlushed(CLOSED_CHANNEL_EXCEPTION, false);
outboundBuffer.failFlushed(FLUSH0_CLOSED_CHANNEL_EXCEPTION, false);
}
} finally {
inFlush0 = false;
@ -851,7 +855,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
* This is needed as otherwise {@link #isActive()} , {@link #isOpen()} and {@link #isWritable()}
* may still return {@code true} even if the channel should be closed as result of the exception.
*/
close(voidPromise(), t, false);
close(voidPromise(), t, FLUSH0_CLOSED_CHANNEL_EXCEPTION, false);
} else {
outboundBuffer.failFlushed(t, true);
}
@ -867,12 +871,13 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
return unsafeVoidPromise;
}
@Deprecated
protected final boolean ensureOpen(ChannelPromise promise) {
if (isOpen()) {
return true;
}
safeSetFailure(promise, CLOSED_CHANNEL_EXCEPTION);
safeSetFailure(promise, ENSURE_OPEN_CLOSED_CHANNEL_EXCEPTION);
return false;
}

View File

@ -27,6 +27,7 @@ import io.netty.util.concurrent.ThreadPerTaskExecutor;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.ReadOnlyIterator;
import io.netty.util.internal.ThrowableUtil;
import java.util.Collections;
import java.util.Iterator;
@ -130,8 +131,9 @@ public class ThreadPerChannelEventLoopGroup extends AbstractEventExecutorGroup i
this.maxChannels = maxChannels;
this.executor = executor;
tooManyChannels = new ChannelException("too many channels (max: " + maxChannels + ')');
tooManyChannels.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
tooManyChannels = ThrowableUtil.unknownStackTrace(
new ChannelException("too many channels (max: " + maxChannels + ')'),
ThreadPerChannelEventLoopGroup.class, "nextChild()");
}
/**

View File

@ -28,9 +28,9 @@ import io.netty.channel.SingleThreadEventLoop;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.SingleThreadEventExecutor;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.InternalThreadLocalMap;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.ThrowableUtil;
import java.net.ConnectException;
import java.net.SocketAddress;
@ -52,7 +52,10 @@ public class LocalChannel extends AbstractChannel {
private static final AtomicReferenceFieldUpdater<LocalChannel, Future> FINISH_READ_FUTURE_UPDATER;
private static final ChannelMetadata METADATA = new ChannelMetadata(false);
private static final int MAX_READER_STACK_DEPTH = 8;
private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException();
private static final ClosedChannelException DO_WRITE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), LocalChannel.class, "doWrite(...)");
private static final ClosedChannelException DO_CLOSE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), LocalChannel.class, "doClose()");
private final ChannelConfig config = new DefaultChannelConfig(this);
// To further optimize this we could write our own SPSC queue.
@ -97,7 +100,6 @@ public class LocalChannel extends AbstractChannel {
AtomicReferenceFieldUpdater.newUpdater(LocalChannel.class, Future.class, "finishReadFuture");
}
FINISH_READ_FUTURE_UPDATER = finishReadFutureUpdater;
CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
public LocalChannel() {
@ -240,7 +242,7 @@ public class LocalChannel extends AbstractChannel {
ChannelPromise promise = connectPromise;
if (promise != null) {
// Use tryFailure() instead of setFailure() to avoid the race against cancel().
promise.tryFailure(CLOSED_CHANNEL_EXCEPTION);
promise.tryFailure(DO_CLOSE_CLOSED_CHANNEL_EXCEPTION);
connectPromise = null;
}
@ -335,7 +337,7 @@ public class LocalChannel extends AbstractChannel {
case BOUND:
throw new NotYetConnectedException();
case CLOSED:
throw CLOSED_CHANNEL_EXCEPTION;
throw DO_WRITE_CLOSED_CHANNEL_EXCEPTION;
case CONNECTED:
break;
}
@ -356,7 +358,7 @@ public class LocalChannel extends AbstractChannel {
peer.inboundBuffer.add(ReferenceCountUtil.retain(msg));
in.remove();
} else {
in.remove(CLOSED_CHANNEL_EXCEPTION);
in.remove(DO_WRITE_CLOSED_CHANNEL_EXCEPTION);
}
} catch (Throwable cause) {
in.remove(cause);

View File

@ -29,7 +29,7 @@ import io.netty.channel.ConnectTimeoutException;
import io.netty.channel.EventLoop;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.ReferenceCounted;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.ThrowableUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@ -50,11 +50,8 @@ public abstract class AbstractNioChannel extends AbstractChannel {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(AbstractNioChannel.class);
private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException();
static {
CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
private static final ClosedChannelException DO_CLOSE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), AbstractNioChannel.class, "doClose()");
private final SelectableChannel ch;
protected final int readInterestOp;
@ -503,7 +500,7 @@ public abstract class AbstractNioChannel extends AbstractChannel {
ChannelPromise promise = connectPromise;
if (promise != null) {
// Use tryFailure() instead of setFailure() to avoid the race against cancel().
promise.tryFailure(CLOSED_CHANNEL_EXCEPTION);
promise.tryFailure(DO_CLOSE_CLOSED_CHANNEL_EXCEPTION);
connectPromise = null;
}

View File

@ -21,7 +21,7 @@ import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener;
import io.netty.util.concurrent.Promise;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.ThrowableUtil;
import java.nio.channels.ClosedChannelException;
import java.util.ArrayDeque;
@ -35,15 +35,12 @@ import java.util.concurrent.TimeoutException;
* number of concurrent connections.
*/
public final class FixedChannelPool extends SimpleChannelPool {
private static final IllegalStateException FULL_EXCEPTION =
new IllegalStateException("Too many outstanding acquire operations");
private static final TimeoutException TIMEOUT_EXCEPTION =
new TimeoutException("Acquire operation took longer then configured maximum time");
static {
FULL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
TIMEOUT_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
private static final IllegalStateException FULL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new IllegalStateException("Too many outstanding acquire operations"),
FixedChannelPool.class, "acquire0(...)");
private static final TimeoutException TIMEOUT_EXCEPTION = ThrowableUtil.unknownStackTrace(
new TimeoutException("Acquire operation took longer then configured maximum time"),
FixedChannelPool.class, "<init>(...)");
public enum AcquireTimeoutAction {
/**

View File

@ -25,8 +25,8 @@ import io.netty.util.AttributeKey;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener;
import io.netty.util.concurrent.Promise;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.ThrowableUtil;
import java.util.Deque;
@ -41,13 +41,12 @@ import static io.netty.util.internal.ObjectUtil.*;
*/
public class SimpleChannelPool implements ChannelPool {
private static final AttributeKey<SimpleChannelPool> POOL_KEY = AttributeKey.newInstance("channelPool");
private static final IllegalStateException FULL_EXCEPTION = new IllegalStateException("ChannelPool full");
private static final IllegalStateException UNHEALTHY_NON_OFFERED_TO_POOL =
new IllegalStateException("Channel is unhealthy not offering it back to pool");
static {
FULL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
UNHEALTHY_NON_OFFERED_TO_POOL.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
private static final IllegalStateException FULL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new IllegalStateException("ChannelPool full"), SimpleChannelPool.class, "releaseAndOffer(...)");
private static final IllegalStateException UNHEALTHY_NON_OFFERED_TO_POOL = ThrowableUtil.unknownStackTrace(
new IllegalStateException("Channel is unhealthy not offering it back to pool"),
SimpleChannelPool.class, "releaseAndOffer(...)");
private final Deque<Channel> deque = PlatformDependent.newConcurrentDeque();
private final ChannelPoolHandler handler;
private final ChannelHealthChecker healthCheck;