[Mono-dev] Mono gac vs Multi gac

Andres G. Aragoneses knocte at gmail.com
Mon Oct 8 00:04:47 UTC 2012


Hey Mono devs,

I've been doing some investigation about the root cause of a bug 
(BXC#6528). You may think it's only being exposed only in serialization, 
but the root cause of the bug is more "core" than that: it is related to 
assembly loading.

By doing some tests in MS.NET I've actually determined that there's no 
bug actually in assembly loading lookup methods, but there's a simple 
but very big difference between the MS gac and the Mono gac: Mono's gac 
is, coincidentally, "mono" (as opposed to "multi"-gac!).

As it is explained here[1]: MS.NET's gacutil will never list two 
different versions of an assembly if those different versions belong to 
different versions of the runtime. So, for example, 
System.Runtime.Serialization.dll v4.0.0.0 is only listed by v4.0's 
gacutil, while System.Runtime.Serialization v3.0 is listed by v3.0 
gacutil. This means that there is a GAC for each runtime version in 
.NET. (This doesn't mean that you cannot install two different versions 
of an assembly in the GAC, I'm just referring to the .NET Framework 
assemblies that Microsoft ships.)

However in Mono, there's only 1 GAC, but the assemblies in it can come 
from different folders [2] thanks to the -gacdir argument (Mono-specific).

This slight difference is a problem, because of the given this scenario:

- Lib-A is built with TargetFramework=3.5, references S.R.S.dll from GAC
- Program-B is built TargetFramework=4.0, references Lib-A.
- You run Program-B in .NET: the version of S.R.S.dll loaded is 4.0.0.0
- You run Program-B in Mono: the version of S.R.S.dll loaded is 3.0.0.0

Now you may be thinking that "there's simply a bug in the assembly 
loader because it should always choose the higher version of a library 
if it exists", to which I would answer: no, if Lib-A is built against 
version 3.5, it has an ".assembly extern" element that points to ".ver 
3:0:0:0" in its IL. If the assembly loader ignored that at will, you 
would be in serious trouble.

Then there's this <assemblyBinding> attribute that forces this kind of 
situation if the new version of the library decides to impose itself by 
overriding this behaviour: [3]. However, Microsoft doesn't ship 
machine.config files with any <assemblyBinding> directive, and I guess 
they are not hardcoding in their assembly-loader a list of assemblies 
that "ship with the framework(TM)" to figure this out. The only 
explanation is that, when a program is run with the v4.0 runtime, it can 
only see the GAC of that version of the runtime.

So then, what to do about this? IMHO opinion it could be fixed in Mono 
but it would be a kind of interesting breaking-change (2.11.4 is still 
considered "alpha" so I guess it's not too late). For example, Mono 
could have a different gacutil command per runtime version, how to call 
them? "gacutil2", "gacutil4" (in the same way it has been done for 
xsp...) maybe?

Let me know your thoughts please. Am I missing something terribly 
obvious? (Or not obvious..?) If not, I'm willing to spend a bit of spare 
time fixing this, and I would appreciate directions.

Thanks,

Andres


[1] 
http://stackoverflow.com/questions/6807694/the-gac-gacutil-exe-and-assembly-cache-viewer

[2] http://www.mono-project.com/Assemblies_and_the_GAC#Using_Multiple_GACs

[3] http://msdn.microsoft.com/en-us/library/twy1dw1e.aspx



More information about the Mono-devel-list mailing list