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

XmlDocsExtensions.GetXmlDocsSummary fails on <inheritdoc/> and concurrent access #132

Open
mediawolf opened this issue Jul 19, 2023 · 0 comments

Comments

@mediawolf
Copy link

mediawolf commented Jul 19, 2023

Commit ID: 33e53f6

Steps:

  • XmlDocsExtensions.GetXmlDocsSummary(...) is called for the same member concurrently
  • That member inherits the documentation from a base class/interface
  • Internally, XmlDocsExtensions.TryGetXmlDocsDocument adds an entry to XmlDocsExtensions.Cache with documentation loaded into XElement. This is the first problematic place, because current implementation of TryGetXmlDocsDocument can return different results for the same key. Be result immutable or if every client got own unique result, then there will be no race condition.
  • However, there are few places which modify cached entry (XElement), by replacing with actual content without any kind of synchronization. Obviously, modifying the same XElement tree concurrently makes Linq goes nuts.

The following snippet will fail with an exception thrown by Linq implementation:

    public interface IMyObject
    {
        /// <summary>
        /// Description
        /// </summary>
        void DoSomething();
    }

    public class MyObject : IMyObject
    {
        /// <inheritdoc/>
        public void DoSomething() { }
    }

    internal class Program
    {
        static void Do()
        {
            typeof(MyObject).GetMember(nameof(MyObject.DoSomething)).Single().GetXmlDocsSummary();
        }

        static void Main(string[] args)
        {
            for (int i = 0; ; ++i)
            {
                Console.WriteLine(i);
                var tasks = new[]
                {
                    Task.Run(Do),
                    Task.Run(Do),
                    Task.Run(Do),
                    Task.Run(Do),
                };
                Task.WaitAll(tasks);
                XmlDocs.ClearCache();
            }
        }
    }

In my case, it's about running unit-tests performing a JSON validation using JsonSchema in parallel. JsonSchema is generated on the fly.

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