提交 3637f8cd 编写于 作者: A Alexander Köplinger 提交者: GitHub

[bcl] Dispose Cecil AssemblyDefinition after usage (#4900)

Follow-up to https://github.com/mono/mono/pull/4899. I audited
all the places in BCL where we made use of Cecil's AssemblyDefinition
and made sure we're properly disposing them and not keeping files
unnecessarily open.

I used InMemory=true in cases where tracking the lifetime would
be complicated. There are also some tests in mcs/tests which I
didn't bother to fix.
上级 087316c8
......@@ -67,33 +67,34 @@ namespace Mono.CodeContracts.Rewrite {
if (options.Debug && options.WritePdbFile)
readerParameters.ReadSymbols = true;
var assembly = this.options.Assembly.IsFilename ?
using (var assembly = this.options.Assembly.IsFilename ?
AssemblyDefinition.ReadAssembly (options.Assembly.Filename, readerParameters) :
AssemblyDefinition.ReadAssembly (options.Assembly.Streams.Assembly, readerParameters);
AssemblyDefinition.ReadAssembly (options.Assembly.Streams.Assembly, readerParameters)) {
if (this.options.ForceAssemblyRename != null) {
assembly.Name.Name = this.options.ForceAssemblyRename;
} else if (this.options.OutputFile.IsSet && this.options.OutputFile.IsFilename) {
assembly.Name.Name = Path.GetFileNameWithoutExtension(this.options.OutputFile.Filename);
}
if (this.options.ForceAssemblyRename != null) {
assembly.Name.Name = this.options.ForceAssemblyRename;
} else if (this.options.OutputFile.IsSet && this.options.OutputFile.IsFilename) {
assembly.Name.Name = Path.GetFileNameWithoutExtension(this.options.OutputFile.Filename);
}
var output = this.options.OutputFile.IsSet ? this.options.OutputFile : this.options.Assembly;
var writerParameters = new WriterParameters ();
if (options.WritePdbFile) {
if (!options.Debug) {
return RewriterResults.Error ("Must specify -debug if using -writePDBFile.");
var output = this.options.OutputFile.IsSet ? this.options.OutputFile : this.options.Assembly;
var writerParameters = new WriterParameters ();
if (options.WritePdbFile) {
if (!options.Debug) {
return RewriterResults.Error ("Must specify -debug if using -writePDBFile.");
}
writerParameters.WriteSymbols = true;
}
writerParameters.WriteSymbols = true;
}
PerformRewrite rewriter = new PerformRewrite (this.options);
rewriter.Rewrite (assembly);
PerformRewrite rewriter = new PerformRewrite (this.options);
rewriter.Rewrite (assembly);
if (output.IsFilename) {
assembly.Write (output.Filename, writerParameters);
} else {
assembly.Write (output.Streams.Assembly, writerParameters);
if (output.IsFilename) {
assembly.Write (output.Filename, writerParameters);
} else {
assembly.Write (output.Streams.Assembly, writerParameters);
}
}
return new RewriterResults (warnings, errors);
......
......@@ -72,7 +72,7 @@ namespace Mono.CodeContracts.Static.AST {
public static AssemblyNode ReadAssembly (string filename)
{
var readerParameters = new ReaderParameters ();
var readerParameters = new ReaderParameters () { InMemory = true };
AssemblyDefinition definition = AssemblyDefinition.ReadAssembly (filename, readerParameters);
return new AssemblyNode (definition);
......
......@@ -44,7 +44,7 @@ namespace GuiCompare {
AssemblyDefinition ProcessFile (string file)
{
AddSearchDirectory (Path.GetDirectoryName (file));
var assembly = AssemblyDefinition.ReadAssembly (file, new ReaderParameters { AssemblyResolver = this });
var assembly = AssemblyDefinition.ReadAssembly (file, new ReaderParameters { AssemblyResolver = this, InMemory = true });
RegisterAssembly (assembly);
return assembly;
......
......@@ -15,10 +15,11 @@ public class MdbDump
return 1;
}
var assembly = AssemblyDefinition.ReadAssembly (args[0]);
using (var assembly = AssemblyDefinition.ReadAssembly (args[0])) {
var f = MonoSymbolFile.ReadSymbolFile (args[0] + ".mdb");
DumpSymbolFile (assembly, f, Console.Out);
var f = MonoSymbolFile.ReadSymbolFile (args[0] + ".mdb");
DumpSymbolFile (assembly, f, Console.Out);
}
return 0;
}
......
......@@ -11,7 +11,7 @@ namespace Mono
{
class AssemblyLocationProvider
{
AssemblyDefinition assembly;
string assemblyFullPath;
Logger logger;
public AssemblyLocationProvider (string assemblyPath, Logger logger)
......@@ -22,85 +22,88 @@ namespace Mono
if (!File.Exists (assemblyPath))
throw new ArgumentException ("assemblyPath does not exist: "+ assemblyPath);
var readerParameters = new ReaderParameters { ReadSymbols = true };
assembly = AssemblyDefinition.ReadAssembly (assemblyPath, readerParameters);
assemblyFullPath = assemblyPath;
}
public bool TryResolveLocation (StackFrameData sfData, SeqPointInfo seqPointInfo)
{
if (!assembly.MainModule.HasSymbols)
return false;
var readerParameters = new ReaderParameters { ReadSymbols = true };
using (var assembly = AssemblyDefinition.ReadAssembly (assemblyFullPath, readerParameters)) {
TypeDefinition type = null;
string[] nested;
if (sfData.TypeFullName.IndexOf ('/') >= 0)
nested = sfData.TypeFullName.Split ('/');
else
nested = sfData.TypeFullName.Split ('+');
var types = assembly.MainModule.Types;
foreach (var ntype in nested) {
if (type == null) {
// Use namespace first time.
type = types.FirstOrDefault (t => t.FullName == ntype);
} else {
type = types.FirstOrDefault (t => t.Name == ntype);
if (!assembly.MainModule.HasSymbols)
return false;
TypeDefinition type = null;
string[] nested;
if (sfData.TypeFullName.IndexOf ('/') >= 0)
nested = sfData.TypeFullName.Split ('/');
else
nested = sfData.TypeFullName.Split ('+');
var types = assembly.MainModule.Types;
foreach (var ntype in nested) {
if (type == null) {
// Use namespace first time.
type = types.FirstOrDefault (t => t.FullName == ntype);
} else {
type = types.FirstOrDefault (t => t.Name == ntype);
}
if (type == null) {
logger.LogWarning ("Could not find type: {0}", ntype);
return false;
}
types = type.NestedTypes;
}
if (type == null) {
logger.LogWarning ("Could not find type: {0}", ntype);
var parensStart = sfData.MethodSignature.IndexOf ('(');
var methodName = sfData.MethodSignature.Substring (0, parensStart).TrimEnd ();
var methodParameters = sfData.MethodSignature.Substring (parensStart);
var methods = type.Methods.Where (m => CompareName (m, methodName) && CompareParameters (m.Parameters, methodParameters)).ToArray ();
if (methods.Length == 0) {
logger.LogWarning ("Could not find method: {0}", methodName);
return false;
}
if (methods.Length > 1) {
logger.LogWarning ("Ambiguous match for method: {0}", sfData.MethodSignature);
return false;
}
var method = methods [0];
types = type.NestedTypes;
}
int ilOffset;
if (sfData.IsILOffset) {
ilOffset = sfData.Offset;
} else {
if (seqPointInfo == null)
return false;
var parensStart = sfData.MethodSignature.IndexOf ('(');
var methodName = sfData.MethodSignature.Substring (0, parensStart).TrimEnd ();
var methodParameters = sfData.MethodSignature.Substring (parensStart);
var methods = type.Methods.Where (m => CompareName (m, methodName) && CompareParameters (m.Parameters, methodParameters)).ToArray ();
if (methods.Length == 0) {
logger.LogWarning ("Could not find method: {0}", methodName);
return false;
}
if (methods.Length > 1) {
logger.LogWarning ("Ambiguous match for method: {0}", sfData.MethodSignature);
return false;
}
var method = methods [0];
ilOffset = seqPointInfo.GetILOffset (method.MetadataToken.ToInt32 (), sfData.MethodIndex, sfData.Offset);
}
int ilOffset;
if (sfData.IsILOffset) {
ilOffset = sfData.Offset;
} else {
if (seqPointInfo == null)
if (ilOffset < 0)
return false;
ilOffset = seqPointInfo.GetILOffset (method.MetadataToken.ToInt32 (), sfData.MethodIndex, sfData.Offset);
}
if (!method.DebugInformation.HasSequencePoints)
return false;
if (ilOffset < 0)
return false;
SequencePoint prev = null;
foreach (var sp in method.DebugInformation.SequencePoints.OrderBy (l => l.Offset)) {
if (sp.Offset >= ilOffset) {
sfData.SetLocation (sp.Document.Url, sp.StartLine);
return true;
}
if (!method.DebugInformation.HasSequencePoints)
return false;
prev = sp;
}
SequencePoint prev = null;
foreach (var sp in method.DebugInformation.SequencePoints.OrderBy (l => l.Offset)) {
if (sp.Offset >= ilOffset) {
sfData.SetLocation (sp.Document.Url, sp.StartLine);
if (prev != null) {
sfData.SetLocation (prev.Document.Url, prev.StartLine);
return true;
}
prev = sp;
}
if (prev != null) {
sfData.SetLocation (prev.Document.Url, prev.StartLine);
return true;
return false;
}
return false;
}
static bool CompareName (MethodDefinition candidate, string expected)
......
......@@ -107,10 +107,11 @@ namespace Mono
continue;
}
var assembly = AssemblyDefinition.ReadAssembly (assemblyPath);
var mvid = assembly.MainModule.Mvid.ToString ("N");
var mvidDir = Path.Combine (msymDir, mvid);
string mvidDir;
using (var assembly = AssemblyDefinition.ReadAssembly (assemblyPath)) {
var mvid = assembly.MainModule.Mvid.ToString ("N");
mvidDir = Path.Combine (msymDir, mvid);
}
if (Directory.Exists (mvidDir)) {
try {
......
......@@ -375,28 +375,29 @@ namespace Mono.Tools {
return 0;
string assemblyName = args [args.Length - 1];
AssemblyDefinition ad = AssemblyDefinition.ReadAssembly (assemblyName);
if (ad != null) {
bool complete = false;
if (declarative) {
// full output (assembly+classes+methods)
complete = ProcessAssemblyComplete (tw, ad);
} else if (xmloutput) {
// full output in XML (for easier diffs after c14n)
complete = ProcessAssemblyXml (tw, ad);
} else {
// default (assembly only)
complete = ProcessAssemblyOnly (tw, ad);
}
using (AssemblyDefinition ad = AssemblyDefinition.ReadAssembly (assemblyName)) {
if (ad != null) {
bool complete = false;
if (declarative) {
// full output (assembly+classes+methods)
complete = ProcessAssemblyComplete (tw, ad);
} else if (xmloutput) {
// full output in XML (for easier diffs after c14n)
complete = ProcessAssemblyXml (tw, ad);
} else {
// default (assembly only)
complete = ProcessAssemblyOnly (tw, ad);
}
if (!complete) {
Console.Error.WriteLine ("Couldn't reflect informations.");
return 1;
if (!complete) {
Console.Error.WriteLine ("Couldn't reflect informations.");
return 1;
}
} else {
Console.Error.WriteLine ("Couldn't load assembly '{0}'.", assemblyName);
return 2;
}
} else {
Console.Error.WriteLine ("Couldn't load assembly '{0}'.", assemblyName);
return 2;
}
tw.Close ();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册