1

A production console application that is shut down via Environment.Exit(0) every night prior midnight, occasionally experiences an exception during .Exit() which leaves the console application hanging, with an "Application has stopped working" screen.

This causes the process not to clean up properly and a relaunch after midnight fails because the prior process is still lingering.

Since I couldn't pin down what causes the exception in Environment.Exit, I'd like to at least handle it gracefully when it occurs and ensure that the process shuts down entirely. To do that, I'd like to simulate a crash after .Exit() but I wasn't able to find a scenario yet that would produce an exception during .Exit().

Does anyone have an idea how an exception during Environment.Exit could be simulated?

TJF
  • 2,248
  • 4
  • 28
  • 43
  • Possible duplicate of [http://stackoverflow.com/questions/18036863/why-does-environment-exit-not-terminate-the-program-anymore](http://stackoverflow.com/questions/18036863/why-does-environment-exit-not-terminate-the-program-anymore) – Reg Edit May 26 '15 at 20:35
  • I don't think this is a duplicate - I'm aware of why there is an exception and I know how to handle it, I was just looking for a sample to reproduce this in an isolated test case – TJF May 26 '15 at 20:40

3 Answers3

3

Sure, it's easy enough to duplicate:

private static void Main()
{
    try
    {
        new ItsATrap();
        Environment.Exit(0);
    }
    catch (Exception ex)
    {
        Console.WriteLine("During exit: {0}", ex);
    }
}

private class ItsATrap
{
    ~ItsATrap()
    {
        throw new InvalidOperationException("Ooops!");
    }
}

Note that the During exit text is never printed in the example above.

You can catch unhandled exceptions by installing a handler like this:

AppDomain.CurrentDomain.UnhandledException += (sender, args)
    => Console.WriteLine("Unhandled: {0}", args.ExceptionObject);

This way you have an opportunity to log them.

So... check your finalizers to see if they can throw.

Also, make sure they don't use other managed resources, as the finalization order isn't deterministic. As usual, Eric Lippert has some good articles to read on the subject.

Lucas Trzesniewski
  • 50,214
  • 11
  • 107
  • 158
1

You have an XY-problem here. You want to simulate an exception because you have no idea what else you could do. Instead of simulating something you don't exactly know, you should try to find out the real cause of the issue and fix it.

Collect a crash dump (MSDN) and load it into Visual Studio. As long as it's somewhere in your C# code, it should show you the line number.

See also: How do I take a good crash dump for .NET? here on Stack Overflow.

Modifying your code as proposed in other answers may change the timing and could just make the exception less likely or occur in different positions. Be happy that you can reproduce the problem and fix it instead of diluting it.

Community
  • 1
  • 1
Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
  • You're assuming this is something that can be fixed. I tracked this down to a 3rd part component which I have no control over. Furthermore, this happens as part of a distributed multi-process system where this issue occurs once every 1-2 months in an order of events that I have not been able to replicate. Since my intended outcome is to shutdown the process, I think the better option is to determine how to shut the process despite an exception being thrown along the way – TJF May 26 '15 at 20:50
  • @TJF: This would have been great information as part of the question. – Thomas Weller May 26 '15 at 20:52
0

Use of a disposed/finalized object can probably cause it. This happens because there is no fixed order for finalization, so for example an hand-made logger that tries to write something on a Stream that has been finalized will cause an exception (hand made because "professional" loggers know of this :-) ).

You could try installing a first-chance exception handler just before calling the Environment.Exit that logs every exception that happens during this time. Something like:

object lck = new object();
AppDomain.CurrentDomain.FirstChanceException += (sender, e) =>
{
    lock (lck)
    {
        File.AppendAllText("log.txt", string.Format("{0}: {1}", DateTime.Now, e.Exception.ToString()));
    }
};

Environment.Exit(0);
xanatos
  • 109,618
  • 12
  • 197
  • 280
  • An application does not crash due to first chance exceptions. Why not install an unhandled exception handler for second chance exceptions instead? – Thomas Weller May 26 '15 at 20:28
  • @ThomasWeller it is called `UnhandledException`... and when I have to debug something, I do prefer to see the `FirstChanceException`, because they often have more information... There could be exceptions that are caused by other exceptions (if the logger is used inside the `catch {}` block, the real exception could cause another exception if the logger is already partially disposed, exception that would hide what is really happening). This is test code. You could log separately both and live happy. – xanatos May 26 '15 at 20:31
  • @xanatos the `catch` block isn't executed if you call `Environment.Exit` – Lucas Trzesniewski May 26 '15 at 20:41