Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TryRecv() = Object reference not set to an instance of an object #20

Closed
xAL95 opened this issue Aug 16, 2022 · 1 comment
Closed

TryRecv() = Object reference not set to an instance of an object #20

xAL95 opened this issue Aug 16, 2022 · 1 comment

Comments

@xAL95
Copy link

xAL95 commented Aug 16, 2022

When sending packets (repeadetly 100+) 3-5 times, then null reference exception occurs.

Important. This ONLY happens when using

new PoolSegManager.Kcp()

and loop without delay/sleep.

With sleep/delay 1 then there is no issue.

Example error code:

var kcp = new PoolSegManager.Kcp(12, this);
kcp.NoDelay(1, 10, 2, 1);
kcp.WndSize(64, 64);
kcp.SetMtu(512);

Task.Run(() =>
            {
                while (true)
                {
                    kcp.Update(DateTime.UtcNow);

                    try
                    {
                        int len;
                        do
                        {
                            var (buffer, avalidSzie) = kcp.TryRecv();
                            len = avalidSzie;
                            if (buffer != null)
                            {
                                buffer.Dispose();
                            }
                        } while (len > 0);
                    }
                    catch(Exception e)
                    {
                        Console.WriteLine(e);
                    }
                }
            });

Untitled

@KumoKyaku
Copy link
Owner

Bug已经复现。
为什么只有PoolSegManager才有Bug?
因为只有PoolSegManager的PoolSegManager.Seg是class,才会出现空引用。

怀疑的两个可能性:
1:TryRecv()的 rcv_queue.Count == 0 判断后,var seq = rcv_queue[0]; 执行前,存在其他线程删除了rcv_queue中的元素。
Q:通过代码分析,删除元素只有 UncheckRecv(Span buffer) 中 rcv_queue.RemoveRange(0, count); 一处。并且只在Recv环节调用,并不存在多线程问题。

2: https://source.dot.net/#System.Private.CoreLib/List.cs,203 rcv_queue.Add(seg);环节,是先增加size,后对下标赋值。
是不是有可能,rcv_queue.Count == 0 判断,var seq = rcv_queue[0]; 正好在List.Add中间执行?
直觉上这种可能性很小,但也不是没有。
一个佐证,但不能确定。在rcv_queue.Count == 0 判断,var seq = rcv_queue[0];两句代码之间插入了日志。Console.WriteLine($"rcv_queue TryRecv正在检测 rcv_queue[0]{rcv_queue[0]} ManagedThreadId{System.Threading.Thread.CurrentThread.ManagedThreadId}");
Bug消失了。

为什么sleep/delay 1 不出现Bug?
测试用例中如果delay,正好可以将Add和Recv函数错开调用。

KumoKyaku added a commit that referenced this issue Aug 17, 2022
KumoKyaku added a commit that referenced this issue Aug 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants