gluck / il-repack

Open-source alternative to ILMerge
Apache License 2.0
1.16k stars 214 forks source link

Mysterious failure in ILpacked application #348

Closed WenningQiu closed 7 months ago

WenningQiu commented 7 months ago

I have a WCF client application that I run ILRepack on to eliminate its dependency assemblies. The ILpacked program works fine on all endpoints except for it gets 400 (Bad Request) response on gzipped endpoints (ones that use GZip encoding).

Below are the messages of working (without ILRepack) and failure (with ILRepack) cases. The only difference I can tell is the content-length header and the message body.

image image

I guess the root cause is some dependency assemblies are missed in the ILRepacked program, but honestly in this case it is not clear to me what missing assembly could cause the observed behavior.

When using ILRepack, do we need to list all assemblies at all reference levels that need to be repacked? or do we just list the top-level dependencies and ILRepack will automatically include the indirectly referenced ones? I think the answer might be the former based on my experience, and that can easily result in some assemblies being missed during repacking.

BTW, below is the dependency assemblies of my application:

                Ben.Demystifier 0.4.0.0 @ .\Ben.Demystifier.dll
                        System.Collections.Immutable 5.0.0.0 => 6.0.0.0 @ .\System.Collections.Immutable.dll
                                System.Memory 4.0.1.1 => 4.0.1.2 @ .\System.Memory.dll
                                        System.Buffers 4.0.3.0 @ .\System.Buffers.dll
                                        System.Numerics.Vectors 4.1.4.0 @ .\System.Numerics.Vectors.dll
                                        System.Runtime.CompilerServices.Unsafe 4.0.4.1 => 6.0.0.0 @ .\System.Runtime.CompilerServices.Unsafe.dll
                                System.Runtime.CompilerServices.Unsafe 6.0.0.0 @ .\System.Runtime.CompilerServices.Unsafe.dll
                        System.Reflection.Metadata 5.0.0.0 @ .\System.Reflection.Metadata.dll
                                *System.Collections.Immutable 5.0.0.0 => 6.0.0.0 @ .\System.Collections.Immutable.dll
                        System.Threading.Tasks.Extensions 4.2.0.1 @ .\System.Threading.Tasks.Extensions.dll
                                *System.Runtime.CompilerServices.Unsafe 4.0.4.1 => 6.0.0.0 @ .\System.Runtime.CompilerServices.Unsafe.dll
                Castle.Core 4.0.0.0 @ .\Castle.Core.dll
                Castle.Facilities.AspNet.SystemWeb 5.0.0.0 @ .\Castle.Facilities.AspNet.SystemWeb.dll
                        Castle.Windsor 5.0.0.0 @ .\Castle.Windsor.dll
                                *Castle.Core 4.0.0.0 @ .\Castle.Core.dll
                *Castle.Windsor 5.0.0.0 @ .\Castle.Windsor.dll
                log4net 2.0.15.0 @ .\log4net.dll
                MessagePack 2.5.0.0 @ .\MessagePack.dll
                        MessagePack.Annotations 2.5.0.0 @ .\MessagePack.Annotations.dll
                        Microsoft.Bcl.AsyncInterfaces 6.0.0.0 @ .\Microsoft.Bcl.AsyncInterfaces.dll
                                *System.Threading.Tasks.Extensions 4.2.0.1 @ .\System.Threading.Tasks.Extensions.dll
                        Microsoft.NET.StringTools 1.0.0.0 @ .\Microsoft.NET.StringTools.dll
                                System.Memory 4.0.1.2 @ .\System.Memory.dll
                                        *System.Buffers 4.0.3.0 @ .\System.Buffers.dll
                                        *System.Numerics.Vectors 4.1.4.0 @ .\System.Numerics.Vectors.dll
                                        *System.Runtime.CompilerServices.Unsafe 4.0.4.1 => 6.0.0.0 @ .\System.Runtime.CompilerServices.Unsafe.dll
                                *System.Runtime.CompilerServices.Unsafe 6.0.0.0 @ .\System.Runtime.CompilerServices.Unsafe.dll
                        System.Buffers 4.0.2.0 => 4.0.3.0 @ .\System.Buffers.dll
                        System.Collections.Immutable 6.0.0.0 @ .\System.Collections.Immutable.dll
                                *System.Memory 4.0.1.1 => 4.0.1.2 @ .\System.Memory.dll
                                *System.Runtime.CompilerServices.Unsafe 6.0.0.0 @ .\System.Runtime.CompilerServices.Unsafe.dll
                        *System.Memory 4.0.1.2 @ .\System.Memory.dll
                        *System.Runtime.CompilerServices.Unsafe 6.0.0.0 @ .\System.Runtime.CompilerServices.Unsafe.dll
                        *System.Threading.Tasks.Extensions 4.2.0.1 @ .\System.Threading.Tasks.Extensions.dll
                Newtonsoft.Json 13.0.0.0 @ .\Newtonsoft.Json.dll
                RabbitMQ.Client 5.0.0.0 @ .\RabbitMQ.Client.dll
                        Microsoft.Diagnostics.Tracing.EventSource 1.1.28.0 @ .\Microsoft.Diagnostics.Tracing.EventSource.dll
                *System.Memory 4.0.1.2 @ .\System.Memory.dll
                System.Net.Http 4.2.0.0 => 4.0.0.0 @ C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Net.Http.dll
                YamlDotNet 13.0.0.0 @ .\YamlDotNet.dll
deniszykov commented 7 months ago

When using ILRepack, do we need to list all assemblies at all reference levels that need to be repacked? or do we just list the top-level dependencies and ILRepack will automatically include the indirectly referenced ones? I think the answer might be the former based on my experience, and that can easily result in some assemblies being missed during repacking.

  1. If one of the dependencies uses reflection by type or assembly names and the assembly it is looking for has been merged, it will break.
  2. If there is loading of assemblies by name or searching for them in neighboring folders, then it will also break if it does not find the dependecies.
  3. Any non-metadata references are not merged (e.g. Assemply.Load, Reflection). You could use ILSpy to look for referenced assembles.
WenningQiu commented 7 months ago

@deniszykov Thanks for the information. Perhaps some libraries are not friendly with ILRepack (case 1 or case 2 might exist somewhere).

KirillOsenkov commented 7 months ago

I’d debug the app with first-chance exceptions enabled, I’m sure there’s an exception you’re not seeing. You can also subscribe to AppDomain.CurrentDomain.FirstChanceException and log them all

WenningQiu commented 7 months ago

I have time to get back to this after wrapping up other issues.

@KirillOsenkov, I tried what you suggested but no FCE was caught.

KirillOsenkov commented 7 months ago

Can you reduce the list of repacked dlls one by one until the bug stops reproducing? This way we can narrow it down to which dll causes the issue.

WenningQiu commented 7 months ago

@KirillOsenkov, The error stops after I remove all DLLs and leave only the EXE.

KirillOsenkov commented 7 months ago

but can you add one .dll at a time and see which dll makes the error return?

WenningQiu commented 7 months ago

The one that makes the error return is my DLL (the one in red box below) which I have complete source code. I guess repacking somehow causes data compression to fail, which results in a bad request.

image

WenningQiu commented 7 months ago

The root cause of 400 Bad Request is that the request message gets compressed twice due to GZipEncodingBehavior being added twice to the endpoint. I need to adjust the application code and configuration file as the full type name of GZipEncodingBehavior is changed after repacking.

image

KirillOsenkov commented 7 months ago

Thanks for figuring this out! We do have some command-line options to strip attributes etc.