5

I have some complex functions that run in an async Task spawned via the TPL, which could occasionally fail in unexpected ways. When such a failure occurs, this indicates a programming error which could have resulted in corrupted program state. Therefore, I don't want my program to catch the exception, handle it and "limp on", I want my process to crash and terminate.

I also want the thing to die in such a way that the Windows Error Reporting system detects it as a crash, and does all the useful debugging things like catching a minidump, sending it to Microsoft, etc.

I realise this may run counter to your opinions of what programs should do in error conditions, but the question is not about that.

The problem I have is, because the exception is raised from a task, it doesn't immediately cause the process to crash. It crashes some time later when the garbage collector, in its wisdom, decides to collect the "unobserved" exception.

I want the process to crash immediately, because...

  • The call stack and thread dump from the actual error is what I want to collect in the crash dump
  • The process "limping on" and crashing some indeterminate time later could cause further damage, as it will be working on a possibly corrupt program state
  • Users get confused about what operation actually caused the crash to occur

So, in short, the question is:

How can I cause my process to crash from an async Task, created with the TPL, such that Windows Error Reporting is able to create a useful minidump?

Thanks in advance!

Mark
  • 1,784
  • 16
  • 26
  • Could explain why you are trying to do this? Do you need logging of some sort? Do you need memory dumps? The "why" can help to find solution. – Andrei Nov 12 '12 at 18:29
  • Yes, I need the memory dumps. And memory dumps from the finalizer thread are useless. – Mark Nov 12 '12 at 18:32
  • As far as I know, memory dumps are normally obtained on a process(application domain) and not a thread. Also, this is a very CRUDE way of debugging an application. Using try...catch inside the task will give you all the info you need on the problem and in easy to read format in 99% of cases. You can log useful data into a file or a database. – Andrei Nov 12 '12 at 19:08
  • try to take a look at this utility: http://technet.microsoft.com/en-us/sysinternals/dd996900.aspx Maybe you can trigger it on an exception(just an idea) and generate the dump file. – Andrei Nov 12 '12 at 19:09
  • 1
    @Andrei As I said, I don't want to argue about how exceptions should be handled. This question is not about that, as that argument can run and run, and has already done so across much of the internet. However, what you may not be aware of is the Windows Error Reporting system, which lets vendors actually capture the crash dumps reported to Microsoft, and debug issues that never get reported by customers, along with actually useful information to debug them. – Mark Nov 13 '12 at 09:47
  • Possible dupe: https://stackoverflow.com/questions/17996738/how-to-make-c-sharp-application-crash. – Ohad Schneider Sep 12 '17 at 15:31

2 Answers2

4

You could try this, or something similar:

public static Task FailFastOnException(this Task task) 
{ 
    task.ContinueWith(c => Environment.FailFast(“Task faulted”, c.Exception), 
        TaskContinuationOptions.OnlyOnFaulted | 
        TaskContinuationOptions.ExecuteSynchronously | 
        TaskContinuationOptions.DetachedFromParent); 
    return task; 
}

and then:

var t = Task.Factory.StartNew(…).FailFastOnException();

We've just used it a lot with "fire and forget" tasks that we want to take down the process if they for some reason fail.

Taken from a blog post written by Stephen Toub: http://blogs.msdn.com/b/pfxteam/archive/2009/05/31/9674669.aspx

Markus
  • 1,614
  • 1
  • 22
  • 32
  • I'm pretty sure `FailFast` is not functionally equivalent to the process crashing due to an exception. Especially when it pertains to `finally` code execution on crash. – Ohad Schneider Sep 12 '17 at 15:22
0

Take a look at ThrowUnobservedTaskExceptions (app.config setting):

<configuration>   
    <runtime>   
        <ThrowUnobservedTaskExceptions enabled="true"/>   
    </runtime>   
</configuration>

If an exception that is associated with a Task has not been observed, there is no Wait operation, the parent is not attached, and the System.Threading.Tasks.Task.Exception property was not read the task exception is considered to be unobserved.

In the .NET Framework 4, by default, if a Task that has an unobserved exception is garbage collected, the finalizer throws an exception and terminates the process. The termination of the process is determined by the timing of garbage collection and finalization.

To make it easier for developers to write asynchronous code based on tasks, the .NET Framework 4.5 changes this default behavior for unobserved exceptions. Unobserved exceptions still cause the UnobservedTaskException event to be raised, but by default, the process does not terminate. Instead, the exception is ignored after the event is raised, regardless of whether an event handler observes the exception.

In the .NET Framework 4.5, you can use the element in an application configuration file to enable the .NET Framework 4 behavior of throwing an exception.

You can also specify the exception behavior in one of the following ways:

  • By setting the environment variable COMPlus_ThrowUnobservedTaskExceptions (set COMPlus_ThrowUnobservedTaskExceptions=1).

  • By setting the registry DWORD value ThrowUnobservedTaskExceptions = 1 in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework key.

Community
  • 1
  • 1
Ohad Schneider
  • 36,600
  • 15
  • 168
  • 198
  • Yeah, the default behaviour changed in 4.5, I was using 4.0 at the time I posed the question. The problem with the unobserved task exception is that it happens some undefined time later, in the context of the GC. – Mark Oct 17 '17 at 20:01