diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index 1d96642596d6c61325fe6867b685c3d3661c2d57..74de8bc06e2db0d935b5baf6b7f7a43de7cf71ed 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -4675,4 +4675,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string literals.
-
\ No newline at end of file
+
+ An error occurred while writing the output file.
+
+
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
index 729180bee5ef743f743c960146263b4cb9667538..b0d2a1c103ba346d6263c39ef3d9051f05278e1f 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
@@ -1320,5 +1320,6 @@ internal enum ErrorCode
ERR_InvalidPathMap = 8101,
ERR_PublicSignButNoKey = 8102,
ERR_TooManyUserStrings = 8103,
+ ERR_PeWritingFailure = 8104,
}
}
diff --git a/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs b/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs
index 4a4d0ff96aac294715613a3ccd942484a7987ac6..a83bce0681cdd35d576d9a5d53bd881d4f82af32 100644
--- a/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs
+++ b/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs
@@ -202,6 +202,7 @@ public override void ReportDuplicateMetadataReferenceWeak(DiagnosticBag diagnost
public override int ERR_MetadataNameTooLong { get { return (int)ErrorCode.ERR_MetadataNameTooLong; } }
public override int ERR_EncReferenceToAddedMember { get { return (int)ErrorCode.ERR_EncReferenceToAddedMember; } }
public override int ERR_TooManyUserStrings { get { return (int)ErrorCode.ERR_TooManyUserStrings; } }
+ public override int ERR_PeWritingFailure { get { return (int)ErrorCode.ERR_PeWritingFailure; } }
public override void ReportInvalidAttributeArgument(DiagnosticBag diagnostics, SyntaxNode attributeSyntax, int parameterIndex, AttributeData attribute)
{
diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/EmitTestStrongNameProvider.cs b/src/Compilers/CSharp/Test/Emit/Attributes/EmitTestStrongNameProvider.cs
index 6f67bc26092b7d7cabb64e325160b2e24dda6e3f..24e6fa4fb790dc4527670e921a56bdbdc00ed41a 100644
--- a/src/Compilers/CSharp/Test/Emit/Attributes/EmitTestStrongNameProvider.cs
+++ b/src/Compilers/CSharp/Test/Emit/Attributes/EmitTestStrongNameProvider.cs
@@ -54,8 +54,8 @@ class C
options: options);
comp.VerifyEmitDiagnostics(
- // error CS7028: Error signing output with public key from container 'RoslynTestContainer' -- This is a test IOException
- Diagnostic(ErrorCode.ERR_PublicKeyContainerFailure).WithArguments("RoslynTestContainer", "This is a test IOException").WithLocation(1, 1));
+ // error CS8104: An error occurred while writing the Portable Executable file.
+ Diagnostic(ErrorCode.ERR_PeWritingFailure).WithArguments("This is a test IOException").WithLocation(1, 1));
}
}
}
diff --git a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs
index d32cf1cd11a6414b33d625098849dd50a8bf7557..2f17b18265ec230ba6aa12cf8221746a2906eff8 100644
--- a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
-using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -2699,10 +2698,16 @@ public void BrokenOutStream()
var compilation = CreateCompilationWithMscorlib(source);
var output = new BrokenStream();
- Assert.Throws(() => compilation.Emit(output));
+ var result = compilation.Emit(output);
+ result.Diagnostics.Verify(
+ // error CS8104: An error occurred while writing the Portable Executable file.
+ Diagnostic(ErrorCode.ERR_PeWritingFailure).WithArguments("I/O error occurred.").WithLocation(1, 1));
output.BreakHow = 1;
- Assert.Throws(() => compilation.Emit(output));
+ result = compilation.Emit(output);
+ result.Diagnostics.Verify(
+ // error CS8104: An error occurred while writing the Portable Executable file.
+ Diagnostic(ErrorCode.ERR_PeWritingFailure).WithArguments("Specified method is not supported.").WithLocation(1, 1));
// disposed stream is not writable
var outReal = new MemoryStream();
@@ -2949,5 +2954,27 @@ static int M(dynamic d, object o)
AssertEx.Equal(expectedNames, actualNames);
}
}
+
+ [Fact]
+ [WorkItem(3240, "https://github.com/dotnet/roslyn/pull/8227")]
+ public void FailingEmitter()
+ {
+ string source = @"
+public class X
+{
+ public static void Main()
+ {
+
+ }
+}";
+ var compilation = CreateCompilationWithMscorlib(source);
+ var broken = new BrokenStream();
+ broken.BreakHow = 0;
+ var result = compilation.Emit(broken);
+ Assert.False(result.Success);
+ result.Diagnostics.Verify(
+ // error CS8104: An error occurred while writing the Portable Executable file.
+ Diagnostic(ErrorCode.ERR_PeWritingFailure).WithArguments("I/O error occurred.").WithLocation(1, 1));
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Emit/Emit/OutputStreams.cs b/src/Compilers/CSharp/Test/Emit/Emit/OutputStreams.cs
index 26880dfaa98e7a167b0fc92e03f7b6a17e859746..674fd11abe81b6173b478c92bdd532764d2b3b10 100644
--- a/src/Compilers/CSharp/Test/Emit/Emit/OutputStreams.cs
+++ b/src/Compilers/CSharp/Test/Emit/Emit/OutputStreams.cs
@@ -20,71 +20,4 @@ public Stream GetXmlInclude(SyntaxTree syntaxTree, string xmlIncludeFile)
throw new NotImplementedException();
}
}
-
- internal class BrokenStream : Stream
- {
- public int BreakHow;
-
- public override bool CanRead
- {
- get { return true; }
- }
-
- public override bool CanSeek
- {
- get { return true; }
- }
-
- public override bool CanWrite
- {
- get { return true; }
- }
-
- public override void Flush()
- {
- }
-
- public override long Length
- {
- get
- {
- return 0;
- }
- }
-
- public override long Position
- {
- get
- {
- return 0;
- }
- set
- {
- if (BreakHow == 1)
- throw new NotSupportedException();
- }
- }
-
- public override int Read(byte[] buffer, int offset, int count)
- {
- return 0;
- }
-
- public override long Seek(long offset, SeekOrigin origin)
- {
- return 0;
- }
-
- public override void SetLength(long value)
- {
- if (BreakHow == 2)
- throw new IOException();
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- if (BreakHow == 0)
- throw new IOException();
- }
- }
}
diff --git a/src/Compilers/Core/Portable/Compilation/Compilation.cs b/src/Compilers/Core/Portable/Compilation/Compilation.cs
index 59d287c537a3e250be61e7a171c82da3f7b4ce58..18796e9b2512886da31ed50922b521ee0f9faf19 100644
--- a/src/Compilers/Core/Portable/Compilation/Compilation.cs
+++ b/src/Compilers/Core/Portable/Compilation/Compilation.cs
@@ -1844,17 +1844,8 @@ private static EmitResult ToEmitResultAndFree(DiagnosticBag diagnostics, bool su
{
Debug.Assert(Options.StrongNameProvider != null);
- // Targeted try-catch for errors during CreateInputStream as found in TFS 1140649
- // TODO: Put this wrapping in PeWriter to catch all potential PE writing exceptions
- try
- {
- signingInputStream = Options.StrongNameProvider.CreateInputStream();
- retStream = signingInputStream;
- }
- catch (Exception e)
- {
- throw new Cci.PeWritingException(e);
- }
+ signingInputStream = Options.StrongNameProvider.CreateInputStream();
+ retStream = signingInputStream;
}
else
{
@@ -1917,9 +1908,8 @@ private static EmitResult ToEmitResultAndFree(DiagnosticBag diagnostics, bool su
}
catch (Cci.PeWritingException e)
{
- // Targeted fix for TFS 1140649
- // TODO: Add resource and better error message for a variety of PE exceptions
- diagnostics.Add(StrongNameKeys.GetError(StrongNameKeys.KeyFilePath, StrongNameKeys.KeyContainer, e.Message, MessageProvider));
+ diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_PeWritingFailure, Location.None, e.Message));
+ return false;
}
catch (ResourceException e)
{
diff --git a/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs b/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs
index 573ecf52a0cc27742586b17bd5fd48cfd7642737..8b089af9febe255999a260ff1b80646d9d7e21c6 100644
--- a/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs
+++ b/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs
@@ -203,6 +203,7 @@ public DiagnosticInfo FilterDiagnosticInfo(DiagnosticInfo diagnosticInfo, Compil
public abstract int ERR_MetadataNameTooLong { get; }
public abstract int ERR_EncReferenceToAddedMember { get; }
public abstract int ERR_TooManyUserStrings { get; }
+ public abstract int ERR_PeWritingFailure { get; }
public abstract void ReportInvalidAttributeArgument(DiagnosticBag diagnostics, SyntaxNode attributeSyntax, int parameterIndex, AttributeData attribute);
public abstract void ReportInvalidNamedArgument(DiagnosticBag diagnostics, SyntaxNode attributeSyntax, int namedArgumentIndex, ITypeSymbol attributeClass, string parameterName);
diff --git a/src/Compilers/Core/Portable/PEWriter/PeWriter.cs b/src/Compilers/Core/Portable/PEWriter/PeWriter.cs
index c04bd639ab0a0751e7aed389df020d477631819e..a42fb3c599bf8e58310b62f232ce4e4d1e859f09 100644
--- a/src/Compilers/Core/Portable/PEWriter/PeWriter.cs
+++ b/src/Compilers/Core/Portable/PEWriter/PeWriter.cs
@@ -12,6 +12,7 @@
using Microsoft.CodeAnalysis;
using Roslyn.Utilities;
using EmitContext = Microsoft.CodeAnalysis.Emit.EmitContext;
+using Microsoft.CodeAnalysis.CodeGen;
namespace Microsoft.Cci
{
@@ -88,10 +89,17 @@ internal sealed class PeWriter
// If PDB writer is given, we have to have PDB path.
Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null);
- var peWriter = new PeWriter(context.Module.Properties, context.Module.Win32Resources, context.Module.Win32ResourceSection, pdbPathOpt, deterministic);
- var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, deterministic, getPortablePdbStreamOpt != null, cancellationToken);
+ try
+ {
+ var peWriter = new PeWriter(context.Module.Properties, context.Module.Win32Resources, context.Module.Win32ResourceSection, pdbPathOpt, deterministic);
+ var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, deterministic, getPortablePdbStreamOpt != null, cancellationToken);
- return peWriter.WritePeToStream(mdWriter, getPeStream, getPortablePdbStreamOpt, nativePdbWriterOpt);
+ return peWriter.WritePeToStream(mdWriter, getPeStream, getPortablePdbStreamOpt, nativePdbWriterOpt);
+ }
+ catch (Exception ex) when (!(ex is PdbWritingException || ex is ResourceException || ex is PermissionSetFileReadException))
+ {
+ throw new PeWritingException(ex);
+ }
}
private bool WritePeToStream(MetadataWriter mdWriter, Func getPeStream, Func getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt)
diff --git a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb
index 2c8ac032348275252aa5a7970050d9e5bc3cbd51..efb2e6f67f649184377605cea3356c8de30a4b4a 100644
--- a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb
+++ b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb
@@ -1682,6 +1682,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
ERR_InvalidPathMap = 37253
ERR_PublicSignNoKey = 37254
ERR_TooManyUserStrings = 37255
+ ERR_PeWritingFailure = 37256
ERR_LastPlusOne
diff --git a/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb b/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb
index b1a90827c2c4239d87ff598780ab59563d795e98..c6bbeb1a62be93f3e029923581dea831a2453c79 100644
--- a/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb
+++ b/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb
@@ -480,6 +480,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return ERRID.ERR_TooManyUserStrings
End Get
End Property
+
+ Public Overrides ReadOnly Property ERR_PeWritingFailure As Integer
+ Get
+ Return ERRID.ERR_PeWritingFailure
+ End Get
+ End Property
End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Portable/VBResources.resx b/src/Compilers/VisualBasic/Portable/VBResources.resx
index a9dcac8d3a5c60be083ca388436529498741c413..7d49b24dd86caea27bddcfa06fa1d9b8c2b85bee 100644
--- a/src/Compilers/VisualBasic/Portable/VBResources.resx
+++ b/src/Compilers/VisualBasic/Portable/VBResources.resx
@@ -5347,4 +5347,7 @@
Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string or XML literals.
-
\ No newline at end of file
+
+ An error occurred while writing the output file.
+
+
diff --git a/src/Compilers/VisualBasic/Test/Emit/Attributes/EmitTestStrongNameProvider.vb b/src/Compilers/VisualBasic/Test/Emit/Attributes/EmitTestStrongNameProvider.vb
index e5b9efc6c2b81664b959ffb00a7b815edbcf8e66..f79884e8ffb1a0bf1205e8889e9f792d9be5be95 100644
--- a/src/Compilers/VisualBasic/Test/Emit/Attributes/EmitTestStrongNameProvider.vb
+++ b/src/Compilers/VisualBasic/Test/Emit/Attributes/EmitTestStrongNameProvider.vb
@@ -54,7 +54,8 @@ End Class
, options:=options)
comp.VerifyEmitDiagnostics(
- Diagnostic(ERRID.ERR_PublicKeyContainerFailure).WithArguments("RoslynTestContainer", "This is a test IOException").WithLocation(1, 1))
+ Diagnostic(ERRID.ERR_PeWritingFailure).WithArguments("This is a test IOException").WithLocation(1, 1))
+
End Sub
End Class
diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb
index 79f1c616cc7b99f321b2cc3c4721bd73e6a5d2ac..1af628835f54ebfaa4dc82353987e42c7edc1b1d 100644
--- a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb
+++ b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb
@@ -2923,5 +2923,89 @@ End Class
End Using
End Sub
+ Private Class FailingStream
+ Inherits Stream
+
+ Shared exception As IOException = New IOException()
+
+ Public Overrides ReadOnly Property CanRead As Boolean
+ Get
+ Return True
+ End Get
+ End Property
+
+ Public Overrides ReadOnly Property CanSeek As Boolean
+ Get
+ Return True
+ End Get
+ End Property
+
+ Public Overrides ReadOnly Property CanWrite As Boolean
+ Get
+ Return True
+ End Get
+ End Property
+
+ Public Overrides ReadOnly Property Length As Long
+ Get
+ Throw exception
+ End Get
+ End Property
+
+ Public Overrides Property Position As Long
+ Get
+ Throw exception
+ End Get
+ Set(value As Long)
+ Throw exception
+ End Set
+ End Property
+
+ Public Overrides Sub Flush()
+ Throw exception
+ End Sub
+
+ Public Overrides Sub SetLength(value As Long)
+ Throw exception
+ End Sub
+
+ Public Overrides Sub Write(buffer() As Byte, offset As Integer, count As Integer)
+ Throw exception
+ End Sub
+
+ Public Overrides Function Read(buffer() As Byte, offset As Integer, count As Integer) As Integer
+ Throw exception
+ End Function
+
+ Public Overrides Function Seek(offset As Long, origin As SeekOrigin) As Long
+ Throw exception
+ End Function
+ End Class
+
+
+ Public Sub FailingEmitter()
+ ' Check that Compilation.Emit actually produces compilation errors.
+ Dim compilation = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime(
+
+
+Module M1
+ Sub Main()
+ End Sub
+End Module
+
+ )
+
+ Dim emitResult As EmitResult
+
+ Using output = New BrokenStream()
+ output.BreakHow = 0
+ emitResult = compilation.Emit(output, Nothing, Nothing, Nothing)
+ End Using
+
+ CompilationUtils.AssertTheseDiagnostics(emitResult.Diagnostics,
+
+BC37256: An error occurred while writing the Portable Executable file.
+)
+ End Sub
End Class
End Namespace
diff --git a/src/Test/Utilities/Shared/Mocks/TestMessageProvider.cs b/src/Test/Utilities/Shared/Mocks/TestMessageProvider.cs
index 4e459dcebf6e1f7ccc60de3ca8fa76ab193ebc6f..291679c387ae9819910300c300c926ca02095d57 100644
--- a/src/Test/Utilities/Shared/Mocks/TestMessageProvider.cs
+++ b/src/Test/Utilities/Shared/Mocks/TestMessageProvider.cs
@@ -362,5 +362,13 @@ public override int ERR_TooManyUserStrings
throw new NotImplementedException();
}
}
+
+ public override int ERR_PeWritingFailure
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
}
}
diff --git a/src/Test/Utilities/Shared/Pe/BrokenStream.cs b/src/Test/Utilities/Shared/Pe/BrokenStream.cs
new file mode 100644
index 0000000000000000000000000000000000000000..24c000eff7fcc62e5abac943b340f8ca8da74edd
--- /dev/null
+++ b/src/Test/Utilities/Shared/Pe/BrokenStream.cs
@@ -0,0 +1,74 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.IO;
+
+namespace Roslyn.Test.Utilities
+{
+ internal class BrokenStream : Stream
+ {
+ public int BreakHow;
+
+ public override bool CanRead
+ {
+ get { return true; }
+ }
+
+ public override bool CanSeek
+ {
+ get { return true; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return true; }
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override long Length
+ {
+ get
+ {
+ return 0;
+ }
+ }
+
+ public override long Position
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ if (BreakHow == 1)
+ throw new NotSupportedException();
+ }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ return 0;
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ return 0;
+ }
+
+ public override void SetLength(long value)
+ {
+ if (BreakHow == 2)
+ throw new IOException();
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ if (BreakHow == 0)
+ throw new IOException();
+ }
+ }
+}