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...
Related
I just ran into a weird scope issue with method parameters in C# and I was wondering if anyone could shed some light on why this is happening or whether it's a bug.
My code essentially is this:
void MyMethod(SqlHelper db, int myInt)
{
try
{
using (db)
{
var bar = OtherMethod(myInt);
On the last line, myInt is throwing an error: "Cannot use local variable 'myInt' before it is declared"
This doesn't throw an error:
void MyMethod(SqlHelper db, int myInt)
{
try
{
var foo = myInt;
using (db)
{
And my workaround for now is:
void MyMethod(SqlHelper db, int myInt)
{
var foo = myInt;
try
{
using (db)
{
var bar = OtherMethod(foo);
But why is this happening? How is myInt falling outside of the scope of the using statement?? I feel personally attacked.
My project is in .Net Framework 4.7.
EDIT: I can't actually reproduce this with the slimmed down version I presented. I will do more research. Thanks to everyone who helped.
EDIT 2: As everyone noted, I left out too much information and the error couldn't be replicated. I found the issue and will leave it here because I am dumb and maybe it will help someone.
Relevant code was this:
void MyMethod(SqlHelper db, int myInt)
{
try
{
using (db = new SqlHelper())
{
var bar = OtherMethod(myInt);
var myInt = SomeMethod(bar);
I had declared another variable with the same name further down within the using statement and Visual Studio didn't like that but didn't know how to tell me. What a day. Thanks again to everyone who came with me on this journey.
I've tried to reproduce the error but was not successful, meaning the unit test that I created works. It compiles and it does not throw any exception. Thus, you would have to provide some more information for us to reproduce the error.
private void MyMethod(IDisposable db, int myInt)
{
try
{
using (db)
{
int bar = OtherMethod(myInt);
}
}
catch (Exception ex)
{
// Do something with the exception.
throw;
}
}
private int OtherMethod(int myInt)
{
return myInt;
}
[Fact]
public void Test1()
{
MyMethod(new MemoryStream(), 10);
}
Note that passing the SqlHelper as a parameter and then putting that in theusing statement is not a good practice. You should avoid that.
One very odd thing you are doing is withyour using statement. You are putting a using on db, an object that someone else has created and passed into this method. When the code leaves your using block it will be disposed and whoever created it will not be able to use it, even though the expect to.
Generally objects should be put in a using block when they are created:
using (var db = new SqlHelper())
{
...
}
Not sure if that's the cause of you're problem, though.
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.
Following code produces same output on 95% of machines, but on several there is difference. In Debug mode there is output:
Changing from New to Fin
OK
but in Release mode:
Changing from New to Fin
The OK line is missing. The project is targeted to .Net 4.0, build with VS 2015. You can download full sample here.
Source code
using System;
namespace Test
{
class Program
{
static void Main(string[] args)
{
Status current = Values.Status;
if (current != Next())
Console.WriteLine("OK");
}
static VO Values = new VO();
private static Status Next()
{
Status res = Status.Fin;
if (Values.Status == Status.New && Values.Cond)
res = Status.Fin;
else if (Values.Status == Status.Fin)
res = Status.Fin;
Log("Changing from {0} to {1}", Values.Status, res);
Values.Status = res;
return res;
}
public static void Log(string format, params object[] args)
{
Console.WriteLine(format, args);
}
}
public class VO
{
public Status Status;
public bool Cond;
}
public enum Status { New, Fin }
}
This is in my opinion the minimal version to reproduce the error. After removing some of the conditions in Next(), inlining Log method, replacing Values.Cond with false causes the application behaves correctly.
Edit: It's not hardware related - operating system was extracted to Hyper-V and the problem persists.
Based on Hans Passant's comment the problem was still reproducible with clrjit.dll version 4.6. After upgrading to 4.7 it disappears.
I am trying to use NGit library in my application (C#, MS.NET 4.0). As we are on MS platform I have rebuilt the NGit for .NET Framework 4.0 under VS 2010. Most things are good and all the functionality works well but the application hangs on its shutdown. VS Debugger shows that some thread from Sharpen lib stays infinitely in the waiting state and nobody signals it to shutdown. That happens when I use any of the instance methods of NGit.Api.Git class (for static methods things seem to be OK). Did anybody experience such issues? Any suggestions?
Example of code using Git class:
Git myrepo = Git.Init().SetDirectory(#"C:\myrepo.git").SetBare(true).Call();
FetchResult fetchResult = myrepo.Fetch()
.SetProgressMonitor(new TextProgressMonitor())
.SetRemote(#"C:\projects\initialrepo")
.SetRefSpecs(new RefSpec("refs/heads/master:refs/heads/master"))
.Call();
//
// Some other work...
//
myrepo.GetRepository().Close();
And here is the place where the thread hangs:
Class Sharpen.ThreadExecutor, line 9 below (St.Monitor.Wait (pendingTasks)):
public void RunPoolThread ()
{
while (!IsTerminated ()) {
try {
Runnable r = null;
lock (pendingTasks) {
freeThreads++;
while (!IsTerminated () && pendingTasks.Count == 0)
ST.Monitor.Wait (pendingTasks);
if (IsTerminated ())
break;
r = pendingTasks.Dequeue ();
}
if (r != null)
r.Run ();
}
catch (ST.ThreadAbortException) {
ST.Thread.ResetAbort ();
}
catch {
}
}
}
I did get the library and ran the tests. I found some of the relevant tests to fail intermittently. I don't know if the test cases are wrong or whether there is an actual problem.
I reported the issue here: https://github.com/slluis/ngit/issues/8
I'll have a look at the particular code you added, I've just seen it
I tested the following code on
Linux (Mono 2.6.7, .NET 3.5)
Linux (Mono 2.11, .NET 4.0)
The problem appears to be that the static BatchingProgressMonitor (which is also constructed when you do not register the TextProgressMonitor) is never 'destructed', meaning that the alarmQueue with it's associated thread-pool is never Shutdown.
If you add the following public method to the class BatchingProgressMonitor:
public static void ShutdownNow()
{
alarmQueue.ShutdownNow();
}
you can have a 'workaround' by calling BatchingProgressMonitor.ShutdownNow() before exiting your application. This WorkedForMeTM. The sample code shows how to do that when you remove the #if/#endif.
.
using System;
using NGit;
using NGit.Api;
using NGit.Transport;
namespace Stacko
{
class MainClass
{
public static void Main (string[] args)
{
Git myrepo = Git.Init().SetDirectory(#"/tmp/myrepo.git").SetBare(true).Call();
{
var fetchResult = myrepo.Fetch()
.SetProgressMonitor(new TextProgressMonitor())
.SetRemote(#"/tmp/initial")
.SetRefSpecs(new RefSpec("refs/heads/master:refs/heads/master"))
.Call();
//
// Some other work...
//
myrepo.GetRepository().Close();
}
System.GC.Collect();
#if false
System.Console.WriteLine("Killing");
BatchingProgressMonitor.ShutdownNow();
#endif
System.Console.WriteLine("Done");
}
}
}
I'll report this at the issue tracker too. Edit Done: here
Cheers,
Seth
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.