Azure / DotNetty

DotNetty project – a port of netty, event-driven asynchronous network application framework
Other
4.09k stars 977 forks source link

When high concurrency under counter problems #475

Open 491134648 opened 5 years ago

491134648 commented 5 years ago

My business code is to implement ChannelHandlerAdapter, and then convert msg to Byte[], and when parsing byte byte arrays at high concurrency, there will be reference counter exceptions System.ArgumentOutOfRangeException: Count must be positive and count must refer to a location within the string/array/collection. Parameter name: count at System.Array.IndexOf[T](T[] array, T value, Int32 startIndex, Int32 count) at System.Collections.Generic.Queue`1.Contains(T item)

`public class SocketByteHandler: ChannelHandlerAdapter {

    readonly bool autoRelease;

    public SocketByteHandler() : this(true)
    {
    }

    protected SocketByteHandler(bool autoRelease)
    {
        this.autoRelease = autoRelease;
    }

    public bool AcceptInboundMessage(object msg) => msg is IByteBuffer;

    public override void ChannelRead(IChannelHandlerContext ctx, object msg)
    {
        bool release = true;
        try
        {
            if (this.AcceptInboundMessage(msg))
            {
                IByteBuffer imsg = (IByteBuffer)msg;
                byte[] result = new byte[imsg.ReadableBytes];
                imsg.ReadBytes(result,0,imsg.ReadableBytes);
                this.ChannelRead0(ctx, result);
            }
            else
            {
                release = false;
                ctx.FireChannelRead(msg);
            }
        }
        finally
        {
            if (autoRelease && release)
            {
                ReferenceCountUtil.Release(msg);
            }
        }
    }

    protected virtual void ChannelRead0(IChannelHandlerContext ctx,byte[] msg)
    {

    }

}`

`public void Init(ServerOptions options,Func handler) { _options = options; if (options.EventLoopCount > 0) { bossGroup = new MultithreadEventLoopGroup(options.EventLoopCount); } else { bossGroup = new MultithreadEventLoopGroup(); } workerGroup = new MultithreadEventLoopGroup(); bootstrap = new ServerBootstrap(); bootstrap.Group(bossGroup, workerGroup); bootstrap.Channel();

        bootstrap.Option(ChannelOption.SoBacklog, _options.SoBacklog);

        bootstrap.ChildOption(ChannelOption.RcvbufAllocator,new AdaptiveRecvByteBufAllocator(64,1048,65536));
        bootstrap.Option(ChannelOption.TcpNodelay, true);
        bootstrap.ChildOption(ChannelOption.SoKeepalive, false);
        bootstrap.ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel =>
        {
            IChannelPipeline pipeline = channel.Pipeline;
            pipeline.AddLast(new MTFrameDecoder(ByteOrderEnum.LittleEndian, AppConfig.ServerOptions.MaxPackLength, AppConfig.ServerOptions.HeadPosition, AppConfig.ServerOptions.HeadLength
                , AppConfig.ServerOptions.LengthAdjustment, 0, true));
            //pipeline.AddLast(new IdleStateHandler(300, 300, 0));
            if (options.ReadTimeout > 0)
            {
                pipeline.AddLast("ReadTimeout", new ReadTimeoutHandler(options.ReadTimeout));
            }
            pipeline.AddLast(handler());
        }));
    }`
yyjdelete commented 5 years ago

It not an reference counter exception. In fact System.Collections.Generic.Queue<T> is not thread-safe and can not be used concurrently. And what's the full stacktrace, looks like an exception in other code. DotNetty only use Queue<T> in DotNetty.Codecs.Http,DotNetty.Handlers.Streams.ChunkedWriteHandler<T> and EmbeddedChannel

491134648 commented 5 years ago

It's supposed to be my business code problem, thank you.