Skip to content
Merged
7 changes: 1 addition & 6 deletions src/linker/Linker.Steps/BaseStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;
using System.Diagnostics;
using Mono.Cecil;

Expand Down Expand Up @@ -68,11 +67,7 @@ public void Process (LinkContext context)
Process ();

foreach (AssemblyDefinition assembly in context.GetAssemblies ()) {
try {
ProcessAssembly (assembly);
} catch (Exception e) {
throw new InternalErrorException ($"Step '{GetType ().Name}' failed when processing assembly '{assembly.FullName}'.", e);
}
ProcessAssembly (assembly);
}

EndProcess ();
Expand Down
7 changes: 1 addition & 6 deletions src/linker/Linker.Steps/MarkStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -554,12 +554,7 @@ void ProcessQueue ()
{
while (!QueueIsEmpty ()) {
(MethodDefinition method, DependencyInfo reason, MessageOrigin origin) = _methods.Dequeue ();
try {
ProcessMethod (method, reason, origin);
} catch (Exception e) when (!(e is LinkerFatalErrorException)) {
throw new LinkerFatalErrorException (
MessageContainer.CreateErrorMessage (origin, DiagnosticId.CouldNotFindMethodInAssembly, method.GetDisplayName (), method.Module.Name), e);
}
ProcessMethod (method, reason, origin);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/linker/Linker.Steps/OutputStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ protected virtual void WriteAssembly (AssemblyDefinition assembly, string direct
try {
assembly.Write (outputName, writerParameters);
} catch (Exception e) {
// We should be okay catching everything here, assembly.Write is all in Cecil and most of the state necessary to debug will be captured in assembly
throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage (null, DiagnosticId.FailedToWriteOutput, outputName), e);
}
}
Expand Down
46 changes: 27 additions & 19 deletions src/linker/Linker/Driver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public static bool ProcessResponseFile (string[] args, out Queue<string> result)
string responseFileName = arg.Substring (1);
using (var responseFileText = new StreamReader (responseFileName))
ParseResponseFile (responseFileText, result);
} catch (Exception e) {
} catch (Exception e) when (e is IOException or ObjectDisposedException) {
Console.Error.WriteLine ("Cannot read response file due to '{0}'", e.Message);
return false;
}
Expand Down Expand Up @@ -767,7 +767,7 @@ protected int SetupContext (ILogger? customLogger = null)
// to the error code.
// May propagate exceptions, which will result in the process getting an
// exit code determined by dotnet.
public int Run (ILogger? customLogger = null, bool throwOnFatalLinkerException = false)
public int Run (ILogger? customLogger = null)
{
int setupStatus = SetupContext (customLogger);
if (setupStatus > 0)
Expand All @@ -780,29 +780,37 @@ public int Run (ILogger? customLogger = null, bool throwOnFatalLinkerException =

try {
p.Process (Context);
} catch (LinkerFatalErrorException lex) {
} catch (Exception e) when (LogFatalError (e)) {
// Unreachable
throw;
}

Context.FlushCachedWarnings ();
Context.Tracer.Finish ();
return Context.ErrorsCount > 0 ? 1 : 0;
}

/// <summary>
/// This method is called in the exception filter for unexpected exceptions.
/// Prints error messages and returns false to avoid catching in the exception filter.
/// </summary>
bool LogFatalError (Exception e)
{
switch (e) {
case LinkerFatalErrorException lex:
Context.LogMessage (lex.MessageContainer);
Console.Error.WriteLine (lex.ToString ());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why delete this line? Is it just a duplicate for some reason?

Copy link
Member Author

@jtschuster jtschuster Jun 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that when the exception causes the program to crash, it will print out all the same information as lex.ToString(), so it isn't necessary to do it in the exception filter too.

Debug.Assert (lex.MessageContainer.Category == MessageCategory.Error);
Debug.Assert (lex.MessageContainer.Code != null);
Debug.Assert (lex.MessageContainer.Code.Value != 0);
if (throwOnFatalLinkerException)
throw;
return lex.MessageContainer.Code ?? 1;
} catch (ResolutionException e) {
Context.LogError (null, DiagnosticId.FailedToResolveMetadataElement, e.Message);
} catch (Exception) {
// Unhandled exceptions are usually linker bugs. Ask the user to report it.
break;
case ResolutionException re:
Context.LogError (null, DiagnosticId.FailedToResolveMetadataElement, re.Message);
break;
default:
Context.LogError (null, DiagnosticId.LinkerUnexpectedError);
// Don't swallow the exception and exit code - rethrow it and let the surrounding tooling decide what to do.
// The stack trace will go to stderr, and the MSBuild task will surface it with High importance.
throw;
} finally {
Context.FlushCachedWarnings ();
Context.Tracer.Finish ();
break;
}

return Context.ErrorsCount > 0 ? 1 : 0;
return false;
}

partial void PreProcessPipeline (Pipeline pipeline);
Expand Down
6 changes: 1 addition & 5 deletions src/tlens/TLens/Runner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,7 @@ public void Process (List<AssemblyDefinition> assemblies)
bool first = true;
foreach (var a in analyzers) {
foreach (var assembly in assemblies) {
try {
a.ProcessAssembly (assembly);
} catch (Exception e) {
throw new ApplicationException ($"Internal error when analyzing '{assembly.FullName}' assembly with '{a.GetType ()}'", e);
}
a.ProcessAssembly (assembly);
}

if (!first)
Expand Down
2 changes: 1 addition & 1 deletion test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public virtual void Link (string[] args, LinkerCustomizations customizations, IL
{
Driver.ProcessResponseFile (args, out var queue);
using (var driver = new TestDriver (queue, customizations)) {
driver.Run (logger, throwOnFatalLinkerException: true);
driver.Run (logger);
}
}
}
Expand Down