After updating Windows 10 to creators update with .net 4.7 I have a critical issue on starting very simple code.
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
class Program
{
private int? m_bool;
private bool prop {get{ return false;}}
void test()
{
//nothing
}
private object Test()
{
if (prop)
{
try
{
test();
}
catch (Exception) {}
m_bool = 1;
}
return null;
}
static void Main(string[] args)
{
new Program().Test();
}
}
Seems the similar issue is https://github.com/dotnet/coreclr/issues/10826
Anyone knows how to avoid that?
The issue is caused when an optimization is running on an unreachable basic block.
In your case the compiler inlines the get_prop method (which unconditionally returns false). This leads to JIT compiler to consider the region as unreachable. Typically the JIT compiler removes the unreachable code before we run the optimization, but adding a try/catch region causes the JIT not to delete these basic blocks.
If you want to prevent the issue you could disable optimizations, disable the inlining of get_prop or change the implementation of the get_prop method to be:
static bool s_alwaysFalse = false;
private bool prop {get{ return s_alwaysFalse;}}
We have had a couple of reports of this issue and we do have a fix ready and it will be provided to users in a upcoming update.
Related
Is there an option/attribute/... that prevents VS's debugger from stopping a debugging session inside a specific method? I'm asking because I'm suffering from the BSoD that the class Ping of .NET 4.0 sometimes triggers. See Blue screen when using Ping for more details.
private async Task<PingReply> PerformPing()
{
// Do not stop debugging inside the using expression
using (var ping = new Ping()) {
return await ping.SendTaskAsync(IPAddress, PingTimeout);
}
}
DebuggerStepthrough
Fun fact you can set it at a method level or a class level.
Instructs the debugger to step through the code instead of stepping into the code. This class cannot be inherited.
Tested with
using System;
using System.Diagnostics;
public class Program
{
[DebuggerStepThrough()]
public static void Main()
{
try
{
throw new ApplicationException("test");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
And the debugger didnt stop in the MAIN method
This answer ignores your BSoD and your Ping class, and focuses on the very interesting question of:
How to prevent the Visual Studio Debugger from stopping inside a specific method
(Note: this is "stopping", with an "o", not "stepping".)
So:
What seems to work nowadays is the [DebuggerHidden] attribute.
So, for example, consider the following method:
///An assertion method that does the only thing that an assertion method is supposed to
///do, which is to throw an "Assertion Failed" exception.
///(Necessary because System.Diagnostics.Debug.Assert does a whole bunch of useless,
///annoying, counter-productive stuff instead of just throwing an exception.)
[DebuggerHidden] //this makes the debugger stop in the calling method instead of here.
[Conditional("DEBUG")]
public static void Assert(bool expression)
{
if (expression)
return;
throw new AssertionFailureException();
}
If you then have the following:
Assert(false);
The debugger will stop on the Assert() invocation, not on the throw statement.
I'm using a very simple ternary expression in my C# code:
helperClass.SomeData = helperClass.HasData ? GetSomeData() : GetSomeOtherData();
In both cases, the functions on each path of the expression return a non-null object, but if I look at the result in the debugger, it is null until I reference it in the code such as using an assert:
Debug.Assert(helperClass.SomeData != null);
This only appears to happen if I use an "x64" or "Any CPU" platform setting in Debug mode. It's fine in "x86" mode.
I try to be very cautious before assuming I've found a bug in the compiler or debugger, but I can't find any other explanation for this behavior.
Here's a full class to do a repro, just call SomeClass.SomeAction() in the debugger in x64 mode and step through to see it:
public class SomeClass {
public bool HasData;
public object SomeData;
private SomeClass() {
HasData = false;
}
public static void SomeAction() {
var helperClass = new SomeClass();
// Exhibits weird debugger behavior of having helperClass.SomeData = null after this line:
helperClass.SomeData = helperClass.HasData ? GetSomeData() : GetSomeOtherData();
// Note that trying helperClass.SomeData.ToString() returns a debugger error saying SomeData is null
// But this code is just fine
//if(helperClass.HasData) {
// helperClass.SomeData = GetSomeData();
//}
//else {
// helperClass.SomeData = GetSomeOtherData();
//}
// In both cases though, after this line things are fine:
Debug.Assert(helperClass.SomeData != null);
}
private static object GetSomeData() {
return new object();
}
private static object GetSomeOtherData() {
return new object();
}
}
Am I missing something or is this a bug in the x64 debugger? I'm using debug mode so no optimizations should be present.
Taking Eric Lippert's advice that this is probably a bug, I've filed an official Connect bug for this issue: https://connect.microsoft.com/VisualStudio/feedback/details/684202
Thanks everyone for your feedback!
UPDATE: They got back to me and said they've fixed this corner case in the next version of the compiler. Hooray! :)
to me this doesn't seem a bug in the debugger but possibly of the compiler...
when changing the code to
{ helperClass.SomeData = helperClass.HasData ? GetSomeData() : GetSomeOtherData(); }
the IL generated is different and the debugger works as expected...
I have a static class which is accessed by multiple threads and uses a ReaderWriterLockSlim in various methods to maintain thread safety. This works fine most of the time, however very intermittently I'm seeing an IOException handle is invalid error being thrown by one particular method as shown in the stack trace below. This has me greatly confused as I didn't even know that System.IO was involved in a ReaderWriterLock.
Any help at all in understanding where the error may be comming from would be greatly appreciated.
Stack Trace:
System.IO.IOException: The handle is invalid.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.Threading.EventWaitHandle.Reset()
at System.Threading.ReaderWriterLockSlim.WaitOnEvent(EventWaitHandle waitEvent, UInt32& numWaiters, Int32 millisecondsTimeout)
at System.Threading.ReaderWriterLockSlim.TryEnterUpgradeableReadLock(Int32 millisecondsTimeout)
Code:
class Class1
{
private static ReaderWriterLockSlim readwriteLock = new ReaderWriterLockSlim();
private const int readwriterlocktimeoutms = 5000;
private static void myMethod(int ID)
{
bool IsTaken = false;
bool isWriteLockTaken = false;
if (!readwriteLock.TryEnterUpgradeableReadLock(readwriterlocktimeoutms))
{
throw new Exception("SafeGetSuItem: Error acquiring read lock");
}
else { IsTaken = true; }
try
{
// do some work which may require upgrading to a write lock depending on particular conditions
}
finally
{
if (IsTaken)
{
try
{
readwriteLock.ExitUpgradeableReadLock();
IsTaken = false;
}
catch
{
throw;
}
}
}
}
}
enter code here
bool IsWriteTaken = false;
try
{
if (!readerwriterlock.TryEnterWriteLock(readerwriterlocktimeout))
{
// log the error
}
else
{
IsWriteTaken = true;
}
if (IsWriteTaken)
{
// do some work
}
}
finally
{
if (IsWriteTaken)
{
try
{
readerwriterlock.ExitWriteLock();
}
catch
{
throw;
}
}
}
This is a little weird. You may have stumbled upon a bug in the WaitHandle class. I picked this apart via Reflector and this is what I am seeing.
Calling Dispose on the ReaderWriterLockSlim will call Close on the EventWaitHandle listed in the stack trace.
Calling Close on a EventWaitHandle attempts to dispose the underlying SafeHandle.
Calling Reset on a EventWaitHandle calls directly into the ResetEvent Win32 API from kernel32.dll and passes in the SafeHandle.
I see no synchronization mechanisms in place that prevent a race between the disposing of a SafeHandle and having that instance consumed by the Win32 API.
Are you calling Dispose on the ReaderWriterLockSlim instance from another thread while TryEnterUpgradeableReadLock could be executing? This seems like the most likely scenario to me. Actually, this is the only scenario that I am seeing that would lead to an IOException being thrown.
It seems to me, based solely on my cursory analysis of the BCL code, that the IOException could be by-design, but it would make a whole lot more sense if Microsoft could somehow generate a ObjectDisposedException instead which happens on every single other attempt I have made to reproduce the problem. I would go ahead and report this to Microsoft.
The following code works fine until I upgrade to .NET 4 (x64)
namespace CrashME
{
class Program
{
private static volatile bool testCrash = false;
private static void Crash()
{
try
{
}
finally
{
HttpRuntime.Cache.Insert("xxx", testCrash);
}
}
static void Main(string[] args)
{
Crash();
// Works on .NET 3.5 , crash on .NET 4
}
}
}
Did I just uncover a runtime bug, or is there some issue with my usage?
This would appear to be a bug in the CLR - you should report it to Microsoft.
Note that the StackOverflowException occurs as the CLR attempts to execute the Crash, not during the execution of the Crash method - the program in fact never enters the method. This would appear to indicate that this is some low-level failure in the CLR. (Also note that the thrown exception also has no stack trace).
This exception is incredibly specific to this situation - changing any one of a number of things fixes this, for example the following code works fine:
private static void Crash()
{
bool testCrash2 = testCrash;
try { }
finally
{
HttpRuntime.Cache.Insert("xxx", testCrash2);
}
}
I would recommend that you report this to Microsoft, but attempt to work around the issue by tweaking your code in the meantime.
I can reproduce it on an x86 machine. The following code also fails:
try
{
}
finally
{
var foo = new List<object>();
foo.Add(testCrash);
}
However, the following code succeeds:
try
{
}
finally
{
var foo = new List<bool>();
foo.Add(testCrash);
}
I thought it might have something to do with the boxing of volatile fields within the finally block, but then I tried the following (which also fails):
try
{
}
finally
{
bool[] foo = new bool[1];
foo[0] = testCrash;
}
Very interesting problem...
Update: I've filed a bug report on Microsoft Connect: https://connect.microsoft.com/VisualStudio/feedback/details/568271/debugger-halting-on-exception-thrown-inside-methodinfo-invoke#details
If you can reproduce this problem on your machine, please upvote the bug so it can be fixed!
Ok I've done some testing and I've reduced the problem to something very simple:
i. Create a method in a new class that throws an exception:
public class Class1 {
public void CallMe() {
string blah = null;
blah.ToLower();
}
}
ii. Create a MethodInfo that points to this method somewhere else:
Type class1 = typeof( Class1 );
Class1 obj = new Class1();
MethodInfo method = class1.GetMethod( "CallMe" );
iii. Wrap a call to Invoke() in a try/catch block:
try {
method.Invoke( obj, null ); // exception is not being caught!
} catch {
}
iv. Run the program without the debugger (works fine).
v. Now run the program with the debugger. The debugger will halt the program when the exception occurs, even though it's wrapped in a catch handler that tries to ignore it. (Even if you put a breakpoint in the catch block it will halt before it reaches it!)
In fact, the exception is happening when you run it without the debugger too. In a simple test project it's getting ignored at some other level, but if your app has any kind of global exception handling, it will get triggered there as well. [see comments]
This is causing me a real headache because it keeps triggering my app's crash-handler, not to mention the pain it is to attempt to debug.
I can reproduce this on my .NET 4 box, and you're right -- it only happens on .NET 4.0.
This smells very much like a bug to me, and should go on MS Connect. Major bummer if this is tripping your crash handler. Sounds like a non-pleasing way to work around this is to wrap the invoked method inside its own handler. :-(
One thing I can not reproduce, though, is tripping the crash handler. Here's my program:
namespace trash {
public class Class1 {
public void CallMe() {
string blah = null;
blah.ToLower();
}
}
class Program {
static void Main(string[] args) {
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
var class1 = typeof(Class1);
var method = class1.GetMethod("CallMe");
try {
var obj = new Class1();
method.Invoke(obj, null); // exception is not being caught!
}
catch (System.Reflection.TargetInvocationException) {
Console.Write("what you would expect");
}
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
Console.Write("it would be horrible if this got tripped but it doesn't!");
}
}
}
You can't catch all exceptions. There's a few assumptions in your example. You are, for instance, assuming the exception was raised on the calling thread. Catching unhandled exceptions on other threads depends on which runtimes you're using (console, winforms, WPF, ASP.Net, etc).
Additionally, calls to System.Environment.FailFast() do not generate any handlable condition - the process is effectively terminated with no chance for intervention.