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

Avoid capture AsyncLocal<T>/CallContext.LogicalData to DotNetty's XThread? #419

Open
yyjdelete opened this issue Aug 29, 2018 · 0 comments

Comments

@yyjdelete
Copy link
Contributor

That will makes them alive forever and may leak something (but lucky only once per IEventLoopGroup) when used with some other frameworks(an HttpContext in aspnet/aspnetcore for me).

An workaround is add some code to any caller for create DotNetty's IEventLoopGroup in user code like the below.
@nayato Should it be apply directly to XThread, like it does in AbstractSocketByteChannel and SocketDatagramChannel? But one problem is the api is only available for netfx and netstandard2.0, so not available for all netcoreapp1.x, and 2.x before directly support for netstandard2.0 is added.

        void CreateLongRunningTask(XParameterizedThreadStart threadStartFunc)
        {
#if NETSTANDARD1_3
            CreateLongRunningTaskUnsafe(threadStartFunc);
#else//NET45 || NETSTANDARD2_0
            if (ExecutionContext.IsFlowSuppressed())
            {
                CreateLongRunningTaskUnsafe(threadStartFunc);
            }
            else
            {
                using (ExecutionContext.SuppressFlow())
                {
                    CreateLongRunningTaskUnsafe(threadStartFunc);
                }
            }
#endif
        }

Test code: an edited version of Echo.Server.

        static async Task RunServerAsync()
        {
            IEventLoopGroup bossGroup;
            IEventLoopGroup workerGroup;

#if NET451
            System.Runtime.Remoting.Messaging.CallContext.LogicalSetData("test001", new { B = 1 });
#else//netcoreapp1.1
            var local = new System.Threading.AsyncLocal<object>();
            local.Value = new { C = 1 };
#endif
            if (ServerSettings.UseLibuv)
            {
                var dispatcher = new DispatcherEventLoopGroup();
                bossGroup = dispatcher;
                workerGroup = new WorkerEventLoopGroup(dispatcher);
            }
            else
            {
                bossGroup = new MultithreadEventLoopGroup(1);
                workerGroup = new MultithreadEventLoopGroup();
            }

#if NET451
            System.Runtime.Remoting.Messaging.CallContext.FreeNamedDataSlot("test001");
            Console.WriteLine("LogicalData(out dotnetty): " + System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("test001"));
#else//netcoreapp1.1
            local.Value = null;
            Console.WriteLine("AsyncLocal(out dotnetty): " + local.Value);
#endif
            bossGroup.GetNext().Execute(() =>
            {
#if NET451
                Console.WriteLine("LogicalData(in dotnetty's boss): " + System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("test001"));
#else//netcoreapp1.1
                Console.WriteLine("AsyncLocal(in dotnetty's boss): " + local.Value);
#endif
            });
            workerGroup.GetNext().Execute(() =>
            {
#if NET451
                Console.WriteLine("LogicalData(in dotnetty's worker): " + System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("test001"));
#else//netcoreapp1.1
                Console.WriteLine("AsyncLocal(in dotnetty's worker): " + local.Value);
#endif
            });
            Console.ReadLine();
        }

        static void Main() => RunServerAsync().Wait();
yyjdelete added a commit to yyjdelete/SpanNetty that referenced this issue Dec 21, 2020
cuteant pushed a commit to cuteant/SpanNetty that referenced this issue Dec 22, 2020
* Use `ExecutionContext.SuppressFlow()` since it's available for all targetFrameworks

And Azure/DotNetty#419

* Use StackTrace class for ResourceLeakDetector, and better performance when enabled

* BIGENDIAN should be checked at runtime

* Better error message

* Use System.Buffers.Binary.BinaryPrimitives for netcoreapp and netstandard
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

1 participant