DebugProvider.Unix.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using Microsoft.Win32.SafeHandles;
  5. namespace System.Diagnostics
  6. {
  7. public partial class DebugProvider
  8. {
  9. private static readonly bool s_shouldWriteToStdErr = Environment.GetEnvironmentVariable("COMPlus_DebugWriteToStdErr") == "1";
  10. public static void FailCore(string stackTrace, string message, string detailMessage, string errorSource)
  11. {
  12. if (s_FailCore != null)
  13. {
  14. s_FailCore(stackTrace, message, detailMessage, errorSource);
  15. return;
  16. }
  17. if (Debugger.IsAttached)
  18. {
  19. Debugger.Break();
  20. }
  21. else
  22. {
  23. // In Core, we do not show a dialog.
  24. // Fail in order to avoid anyone catching an exception and masking
  25. // an assert failure.
  26. DebugAssertException ex;
  27. if (message == string.Empty)
  28. {
  29. ex = new DebugAssertException(stackTrace);
  30. }
  31. else if (detailMessage == string.Empty)
  32. {
  33. ex = new DebugAssertException(message, stackTrace);
  34. }
  35. else
  36. {
  37. ex = new DebugAssertException(message, detailMessage, stackTrace);
  38. }
  39. Environment.FailFast(ex.Message, ex, errorSource);
  40. }
  41. }
  42. public static void WriteCore(string message)
  43. {
  44. if (s_WriteCore != null)
  45. {
  46. s_WriteCore(message);
  47. return;
  48. }
  49. WriteToDebugger(message);
  50. if (s_shouldWriteToStdErr)
  51. {
  52. WriteToStderr(message);
  53. }
  54. }
  55. private static void WriteToDebugger(string message)
  56. {
  57. if (Debugger.IsLogging())
  58. {
  59. Debugger.Log(0, null, message);
  60. }
  61. else
  62. {
  63. Interop.Sys.SysLog(Interop.Sys.SysLogPriority.LOG_USER | Interop.Sys.SysLogPriority.LOG_DEBUG, "%s", message);
  64. }
  65. }
  66. private static void WriteToStderr(string message)
  67. {
  68. // We don't want to write UTF-16 to a file like standard error. Ideally we would transcode this
  69. // to UTF8, but the downside of that is it pulls in a bunch of stuff into what is ideally
  70. // a path with minimal dependencies (as to prevent re-entrency), so we'll take the strategy
  71. // of just throwing away any non ASCII characters from the message and writing the rest
  72. const int BufferLength = 256;
  73. unsafe
  74. {
  75. byte* buf = stackalloc byte[BufferLength];
  76. int bufCount;
  77. int i = 0;
  78. while (i < message.Length)
  79. {
  80. for (bufCount = 0; bufCount < BufferLength && i < message.Length; i++)
  81. {
  82. if (message[i] <= 0x7F)
  83. {
  84. buf[bufCount] = (byte)message[i];
  85. bufCount++;
  86. }
  87. }
  88. int totalBytesWritten = 0;
  89. while (bufCount > 0)
  90. {
  91. int bytesWritten = Interop.Sys.Write(2 /* stderr */, buf + totalBytesWritten, bufCount);
  92. if (bytesWritten < 0)
  93. {
  94. // On error, simply stop writing the debug output. This could commonly happen if stderr
  95. // was piped to a program that ended before this program did, resulting in EPIPE errors.
  96. return;
  97. }
  98. bufCount -= bytesWritten;
  99. totalBytesWritten += bytesWritten;
  100. }
  101. }
  102. }
  103. }
  104. }
  105. }