RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.67k stars 1.23k forks source link

[Concurrency bug] System.InvalidOperationException: Collection was modified #2890

Open vchirikov opened 4 years ago

vchirikov commented 4 years ago

Hi I use NSwag.WebApi code generation and run into some concurrency problems. The worst thing is that the exception is silently ignored here,

System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.'

Stack:

    System.Private.CoreLib.dll!System.ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion()   Unknown
    System.Private.CoreLib.dll!System.Collections.Generic.Dictionary<System.__Canon, System.__Canon>.KeyCollection.Enumerator.MoveNext()    Unknown
    DotLiquid.dll!DotLiquid.Hash.Merge(System.Collections.Generic.IDictionary<string, object> otherValues = {DotLiquid.Hash})   Unknown
    NJsonSchema.CodeGeneration.dll!NJsonSchema.CodeGeneration.DefaultTemplateFactory.TemplateTag.CreateModelWithParentContext(DotLiquid.Context context = {DotLiquid.Context})  Unknown
    NJsonSchema.CodeGeneration.dll!NJsonSchema.CodeGeneration.DefaultTemplateFactory.TemplateTag.Render(DotLiquid.Context context = {DotLiquid.Context}, System.IO.TextWriter result = {System.IO.StringWriter})    Unknown
    DotLiquid.dll!DotLiquid.Block.RenderAll(System.Collections.Generic.List<object> list = Count = 9, DotLiquid.Context context = {DotLiquid.Context}, System.IO.TextWriter result = {System.IO.StringWriter})  Unknown
    DotLiquid.dll!DotLiquid.Tags.For.Render.AnonymousMethod__0()    Unknown
    DotLiquid.dll!DotLiquid.Context.Stack(DotLiquid.Hash newScope = {DotLiquid.Hash}, System.Action callback = {Method = {System.Reflection.RuntimeMethodInfo}})    Unknown
    DotLiquid.dll!DotLiquid.Context.Stack(System.Action callback = {Method = {System.Reflection.RuntimeMethodInfo}})    Unknown
    DotLiquid.dll!DotLiquid.Tags.For.Render(DotLiquid.Context context = {DotLiquid.Context}, System.IO.TextWriter result = {System.IO.StringWriter})    Unknown
    DotLiquid.dll!DotLiquid.Block.RenderAll(System.Collections.Generic.List<object> list = Count = 5, DotLiquid.Context context = {DotLiquid.Context}, System.IO.TextWriter result = {System.IO.StringWriter})  Unknown
    DotLiquid.dll!DotLiquid.Tags.If.Render.AnonymousMethod__0() Unknown
    DotLiquid.dll!DotLiquid.Context.Stack(DotLiquid.Hash newScope = {DotLiquid.Hash}, System.Action callback = {Method = {System.Reflection.RuntimeMethodInfo}})    Unknown
    DotLiquid.dll!DotLiquid.Context.Stack(System.Action callback = {Method = {System.Reflection.RuntimeMethodInfo}})    Unknown
    DotLiquid.dll!DotLiquid.Tags.If.Render(DotLiquid.Context context = {DotLiquid.Context}, System.IO.TextWriter result = {System.IO.StringWriter}) Unknown
    DotLiquid.dll!DotLiquid.Block.RenderAll(System.Collections.Generic.List<object> list = Count = 19, DotLiquid.Context context = {DotLiquid.Context}, System.IO.TextWriter result = {System.IO.StringWriter}) Unknown
    DotLiquid.dll!DotLiquid.Tags.If.Render.AnonymousMethod__0() Unknown
    DotLiquid.dll!DotLiquid.Context.Stack(DotLiquid.Hash newScope = {DotLiquid.Hash}, System.Action callback = {Method = {System.Reflection.RuntimeMethodInfo}})    Unknown
    DotLiquid.dll!DotLiquid.Context.Stack(System.Action callback = {Method = {System.Reflection.RuntimeMethodInfo}})    Unknown
    DotLiquid.dll!DotLiquid.Tags.If.Render(DotLiquid.Context context = {DotLiquid.Context}, System.IO.TextWriter result = {System.IO.StringWriter}) Unknown
    DotLiquid.dll!DotLiquid.Block.RenderAll(System.Collections.Generic.List<object> list = Count = 1, DotLiquid.Context context = {DotLiquid.Context}, System.IO.TextWriter result = {System.IO.StringWriter})  Unknown
    DotLiquid.dll!DotLiquid.Block.Render(DotLiquid.Context context = {DotLiquid.Context}, System.IO.TextWriter result = {System.IO.StringWriter})   Unknown
    DotLiquid.dll!DotLiquid.Document.Render(DotLiquid.Context context = {DotLiquid.Context}, System.IO.TextWriter result = {System.IO.StringWriter})    Unknown
    DotLiquid.dll!DotLiquid.Template.RenderInternal(System.IO.TextWriter result = {System.IO.StringWriter}, DotLiquid.RenderParameters parameters = {DotLiquid.RenderParameters})   Unknown
    DotLiquid.dll!DotLiquid.Template.Render(System.IO.TextWriter writer = {System.IO.StringWriter}, DotLiquid.RenderParameters parameters = {DotLiquid.RenderParameters})   Unknown
    DotLiquid.dll!DotLiquid.Template.Render(DotLiquid.RenderParameters parameters = {DotLiquid.RenderParameters})   Unknown
    NJsonSchema.CodeGeneration.dll!NJsonSchema.CodeGeneration.DefaultTemplateFactory.LiquidTemplate.Render()    Unknown
    NJsonSchema.CodeGeneration.dll!NJsonSchema.CodeGeneration.CodeArtifact.CodeArtifact(string typeName = "CallAssistantDiscoveryApi", NJsonSchema.CodeGeneration.CodeArtifactType type = Class, NJsonSchema.CodeGeneration.CodeArtifactLanguage language = CSharp, NJsonSchema.CodeGeneration.CodeArtifactCategory category = Client, NJsonSchema.CodeGeneration.ITemplate template = {NJsonSchema.CodeGeneration.DefaultTemplateFactory.LiquidTemplate})  Unknown
    NSwag.CodeGeneration.TypeScript.dll!NSwag.CodeGeneration.TypeScript.TypeScriptClientGenerator.GenerateClientTypes(string controllerName = "CallAssistantDiscoveryApi", string controllerClassName = "CallAssistantDiscoveryApi", System.Collections.Generic.IEnumerable<NSwag.CodeGeneration.TypeScript.Models.TypeScriptOperationModel> operations = Count = 28)   Unknown
    System.Private.CoreLib.dll!System.Collections.Generic.List<NJsonSchema.CodeGeneration.CodeArtifact>.InsertRange(int index = 0, System.Collections.Generic.IEnumerable<NJsonSchema.CodeGeneration.CodeArtifact> collection)  Unknown
    System.Private.CoreLib.dll!System.Collections.Generic.List<System.__Canon>.AddRange(System.Collections.Generic.IEnumerable<System.__Canon> collection)  Unknown
    NSwag.CodeGeneration.dll!NSwag.CodeGeneration.ClientGeneratorBase<NSwag.CodeGeneration.TypeScript.Models.TypeScriptOperationModel, NSwag.CodeGeneration.TypeScript.Models.TypeScriptParameterModel, NSwag.CodeGeneration.TypeScript.Models.TypeScriptResponseModel>.GenerateAllClientTypes()    Unknown
    NSwag.CodeGeneration.dll!NSwag.CodeGeneration.ClientGeneratorBase<NSwag.CodeGeneration.TypeScript.Models.TypeScriptOperationModel, NSwag.CodeGeneration.TypeScript.Models.TypeScriptParameterModel, NSwag.CodeGeneration.TypeScript.Models.TypeScriptResponseModel>.GenerateFile(NSwag.CodeGeneration.ClientGeneratorOutputType outputType = Full)  Unknown
    NSwag.CodeGeneration.dll!NSwag.CodeGeneration.ClientGeneratorBase<NSwag.CodeGeneration.TypeScript.Models.TypeScriptOperationModel, NSwag.CodeGeneration.TypeScript.Models.TypeScriptParameterModel, NSwag.CodeGeneration.TypeScript.Models.TypeScriptResponseModel>.GenerateFile()  Unknown

Can the code generation produce different results because of this?

btw: 'System.ArgumentException' with System.Linq.Expressions is also silently ignored somewhere (don't remember where, but if you want I can create new issue for this.)

RicoSuter commented 4 years ago

I saw this problem in concurrent tests (NJsonSchema) but couldn't figure out why this happens - there is no shared state in the code gens so maybe it’s a dotliquid bug. Maybe you are more lucky?