[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