Skip to content

Commit 8e19680

Browse files
Change how we write to stderr from CoreLib (dotnet#1377)
We write to stderr from CoreLib for two reasons: 1. FailFast 2. Unhandled exception (also FailFast in a way) We're using a roundabout way to use `Console.Error.WriteLine` but that has problems for FailFast because we then don't fail fast enough (dotnet#1277). This inlines enough of writing to stderr that we can get rid of System.Console dependency. Fixes dotnet#1277.
1 parent be2c195 commit 8e19680

File tree

18 files changed

+75
-79
lines changed

18 files changed

+75
-79
lines changed

docs/using-nativeaot/optimizing.md

-1
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,4 @@ Debugging symbols (data about your program required for debugging) is by default
4949
No action is needed on Windows since the platform convention is to generate debug information into a separate file (`*.pdb`).
5050

5151
## Advanced options
52-
* `<IlcDisableUnhandledExceptionExperience>true</IlcDisableUnhandledExceptionExperience>`: disables code that prints stack traces for unhandled exceptions to the console.
5352
* `<IlcSystemModule>classlibmodule</IlcSystemModule>`: Name of the module which contains basic classes. When specified, disable automatic referencing of the `System.Private.CoreLib` and other libraries. See https://github.com/MichalStrehovsky/zerosharp for example of usage.

src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets

-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ The .NET Foundation licenses this file to you under the MIT license.
9898
<AutoInitializedAssemblies Include="System.Private.Reflection.Execution" Condition="$(IlcDisableReflection) != 'true'" />
9999
<AutoInitializedAssemblies Include="System.Private.DisabledReflection" Condition="$(IlcDisableReflection) == 'true'" />
100100
<AutoInitializedAssemblies Include="System.Private.Interop" />
101-
<AutoInitializedAssemblies Include="System.Private.DeveloperExperience.Console" Condition="$(IlcDisableUnhandledExceptionExperience) != 'true'" />
102101
</ItemGroup>
103102

104103
<ItemGroup>

src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs

-16
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,6 @@ private static bool IsMetadataStackTraceResolutionDisabled()
3333
return disableMetadata;
3434
}
3535

36-
internal static void WriteLine(string s)
37-
{
38-
// We need to write into stderr, but CoreLib doesn't have a way to write to stderr, so we rely
39-
// on a separate library on the startup path to hook this up.
40-
// If nothing hooked it up, just use Debug.WriteLine.
41-
Action<string> writeLineMethod = AppContext.GetData("System.Runtime.ExceptionServices.WriteLine") as Action<string>;
42-
if (writeLineMethod != null)
43-
{
44-
writeLineMethod(s);
45-
}
46-
else
47-
{
48-
Debug.WriteLine(s);
49-
}
50-
}
51-
5236
public virtual string CreateStackTraceString(IntPtr ip, bool includeFileInfo)
5337
{
5438
if (!IsMetadataStackTraceResolutionDisabled())

src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs

+18-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Collections.Generic;
54
using System.Diagnostics;
65
using System.Diagnostics.CodeAnalysis;
76
using System.Runtime;
87
using System.Runtime.CompilerServices;
9-
using System.Runtime.InteropServices;
10-
using System.Threading;
8+
119
using Internal.DeveloperExperience;
1210
using Internal.Runtime.Augments;
1311

@@ -241,10 +239,23 @@ internal static void FailFast(string message, Exception exception, RhFailFastRea
241239

242240
if (!minimalFailFast)
243241
{
244-
string output = (exception != null) ?
245-
"Unhandled Exception: " + exception.ToString()
246-
: message;
247-
DeveloperExperience.WriteLine(output);
242+
string prefix;
243+
string outputMessage;
244+
if (exception != null)
245+
{
246+
prefix = "Unhandled Exception: ";
247+
outputMessage = exception.ToString();
248+
}
249+
else
250+
{
251+
prefix = "Process terminated. ";
252+
outputMessage = message;
253+
}
254+
255+
Internal.Console.Error.Write(prefix);
256+
if (outputMessage != null)
257+
Internal.Console.Error.Write(outputMessage);
258+
Internal.Console.Error.Write(Environment.NewLine);
248259

249260
#if FEATURE_DUMP_DEBUGGING
250261
GenerateExceptionInformationForDump(exception, IntPtr.Zero);

src/coreclr/tools/aot/ILCompiler/repro/repro.csproj

-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
<ReproResponseLines Include="--initassembly:System.Private.TypeLoader" />
2828
<ReproResponseLines Include="--initassembly:System.Private.Reflection.Execution" />
2929
<ReproResponseLines Include="--initassembly:System.Private.Interop" />
30-
<ReproResponseLines Include="--initassembly:System.Private.DeveloperExperience.Console" />
3130
<ReproResponseLines Include="--directpinvokelist:$(RuntimeBinDir)build\WindowsAPIs.txt" />
3231
<ReproResponseLines Include="--stacktracedata" />
3332
<ReproResponseLines Include="--scanreflection" />

src/libraries/Common/src/Interop/Unix/System.Native/Interop.Log.cs

+3
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,8 @@ internal static partial class Sys
1010
{
1111
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Log")]
1212
internal static extern unsafe void Log(byte* buffer, int count);
13+
14+
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LogError")]
15+
internal static extern unsafe void LogError(byte* buffer, int count);
1316
}
1417
}

src/libraries/Native/Unix/System.Native/entrypoints.c

+1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ static const Entry s_sysNative[] =
112112
DllImportEntry(SystemNative_LChflagsCanSetHiddenFlag)
113113
DllImportEntry(SystemNative_ReadProcessStatusInfo)
114114
DllImportEntry(SystemNative_Log)
115+
DllImportEntry(SystemNative_LogError)
115116
DllImportEntry(SystemNative_AlignedAlloc)
116117
DllImportEntry(SystemNative_AlignedFree)
117118
DllImportEntry(SystemNative_AlignedRealloc)

src/libraries/Native/Unix/System.Native/pal_log.c

+6
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,9 @@ void SystemNative_Log(uint8_t* buffer, int32_t length)
1111
fwrite(buffer, 1, (size_t)length, stdout);
1212
fflush(stdout);
1313
}
14+
15+
void SystemNative_LogError(uint8_t* buffer, int32_t length)
16+
{
17+
fwrite(buffer, 1, (size_t)length, stderr);
18+
fflush(stderr);
19+
}

src/libraries/Native/Unix/System.Native/pal_log.h

+1
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
#include "pal_types.h"
88

99
PALEXPORT void SystemNative_Log(uint8_t* buffer, int32_t length);
10+
PALEXPORT void SystemNative_LogError(uint8_t* buffer, int32_t length);

src/libraries/Native/Unix/System.Native/pal_log.m

+5
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,8 @@ void SystemNative_Log (uint8_t* buffer, int32_t length)
3939
}
4040
[msg release];
4141
}
42+
43+
void SystemNative_LogError (uint8_t* buffer, int32_t length)
44+
{
45+
SystemNative_Log (buffer, length);
46+
}

src/libraries/NetCoreAppLibrary.props

-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@
7777
System.Numerics.Vectors;
7878
System.ObjectModel;
7979
System.Private.DataContractSerialization;
80-
System.Private.DeveloperExperience.Console;
8180
System.Private.Runtime.InteropServices.JavaScript;
8281
System.Private.Uri;
8382
System.Private.Xml;

src/libraries/System.Private.CoreLib/src/Internal/Console.Unix.cs

+12
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,17 @@ public static unsafe void Write(string s)
1616
Interop.Sys.Log(pBytes, bytes.Length);
1717
}
1818
}
19+
20+
public static partial class Error
21+
{
22+
public static unsafe void Write(string s)
23+
{
24+
byte[] bytes = Encoding.UTF8.GetBytes(s);
25+
fixed (byte* pBytes = bytes)
26+
{
27+
Interop.Sys.LogError(pBytes, bytes.Length);
28+
}
29+
}
30+
}
1931
}
2032
}

src/libraries/System.Private.CoreLib/src/Internal/Console.Windows.cs

+26-5
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,36 @@ namespace Internal
88
{
99
public static partial class Console
1010
{
11-
private static readonly IntPtr s_outputHandle =
12-
Interop.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_OUTPUT_HANDLE);
11+
public static void Write(string s)
12+
{
13+
WriteCore(Interop.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_OUTPUT_HANDLE), s);
14+
}
15+
16+
public static partial class Error
17+
{
18+
public static void Write(string s)
19+
{
20+
WriteCore(Interop.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_ERROR_HANDLE), s);
21+
}
22+
}
1323

14-
public static unsafe void Write(string s)
24+
private static unsafe void WriteCore(IntPtr handle, string s)
1525
{
16-
byte[] bytes = Encoding.UTF8.GetBytes(s);
26+
int bufferSize = s.Length * 4;
27+
Span<byte> bytes = bufferSize < 1024 ? stackalloc byte[bufferSize] : new byte[bufferSize];
28+
int cbytes;
29+
30+
fixed (char* pChars = s)
31+
fixed (byte* pBytes = bytes)
32+
{
33+
cbytes = Interop.Kernel32.WideCharToMultiByte(
34+
Interop.Kernel32.GetConsoleOutputCP(),
35+
0, pChars, s.Length, pBytes, bytes.Length, IntPtr.Zero, IntPtr.Zero);
36+
}
37+
1738
fixed (byte* pBytes = bytes)
1839
{
19-
Interop.Kernel32.WriteFile(s_outputHandle, pBytes, bytes.Length, out _, IntPtr.Zero);
40+
Interop.Kernel32.WriteFile(handle, pBytes, cbytes, out _, IntPtr.Zero);
2041
}
2142
}
2243
}

src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems

+3
Original file line numberDiff line numberDiff line change
@@ -1511,6 +1511,9 @@
15111511
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetComputerName.cs">
15121512
<Link>Common\Interop\Windows\Kernel32\Interop.GetComputerName.cs</Link>
15131513
</Compile>
1514+
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetConsoleOutputCP.cs">
1515+
<Link>Common\Interop\Windows\Kernel32\Interop.GetConsoleOutputCP.cs</Link>
1516+
</Compile>
15141517
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCPInfo.cs">
15151518
<Link>Common\Interop\Windows\Kernel32\Interop.GetCPInfo.cs</Link>
15161519
</Compile>

src/libraries/System.Private.DeveloperExperience.Console/Directory.Build.props

-6
This file was deleted.

src/libraries/System.Private.DeveloperExperience.Console/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs

-21
This file was deleted.

src/libraries/System.Private.DeveloperExperience.Console/src/System.Private.DeveloperExperience.Console.csproj

-15
This file was deleted.

src/libraries/pkg/baseline/packageIndex.json

-5
Original file line numberDiff line numberDiff line change
@@ -4830,11 +4830,6 @@
48304830
"4.1.2.0": "4.3.0"
48314831
}
48324832
},
4833-
"System.Private.DeveloperExperience.Console": {
4834-
"InboxOn": {
4835-
"net5.0": "5.0.0.0"
4836-
}
4837-
},
48384833
"System.Private.Runtime.InteropServices.JavaScript": {
48394834
"InboxOn": {
48404835
"net5.0": "5.0.0.0",

0 commit comments

Comments
 (0)