tags:

views:

454

answers:

10

We run a C# console application that starts multiple threads to do work. The main function looks something like this:

        try
        {
            DoWork();
        }
        catch (Exception err)
        {
            Logging.Log("Exception " + err.ToString());
        }
        Logging.Log("Finished");

The DoWork() function reads new jobs from a database, and spawns threads to process one work item each. Since last week, the application has started disappearing mysteriously. It disappears from the processes list and there is no entry in the event logs. The log file shows work up to a certain point: it does not log an exception, or the "Finished" line.

Any clue(s) on how a C# application can vanish like that?

EDIT: Threads are created like:

new Thread(SomeObj.StartFunc).Start();

Some of the disappearances occur when no threads are running.

P.S. We installed DebugDiag with a rule to create a crash dump whenever our program crashed. It did not create any dump files when the process disappeared.

+9  A: 

You need to have a similar catch block at the top level of the function that every thread works. If there is an uncaught exception on a thread it will kill the app, the catch block on the main thread is not going to help.

Grzenio
The thread does have a try/catch block in it's top level function.
Andomar
+2  A: 

perhaps it is the Logging.Log function that throws your exception?

Gregoire
The logging function is simple and there's plenty disk space available. The program keeps a single StreamWriter open while it runs, and protects access to it with a lock {} section.
Andomar
A: 

Does it always crash/stop at the same point? Where is this running? Could someone/something be killing the process?

Chuck
Stops occur at random times, this week 5 times total. In theory, I suppose someone could login and kill the process, but that sounds a little paranoid.
Andomar
Agreed re: the paranoid but I've had someone do that in the past. They didn't know what it was so they killed it when they saw it and didn't bother to ask.
Chuck
+2  A: 

A console program quits when the main function exits. Since DoWork just spawns a few threads it's returning control to main right away, and since Main has nothing else to do it exits and the program ends. At this time the threads spawned by DoWork are also killed.

That it worked before means either there was something in DoWork() to wait on those threads that now returns right away (is broken) or that part still works but a thread that used to take a long time to return now aborts and returns right away.

Joel Coehoorn
The DoWork() function does not return before all the work is done, and all threads have shut down. The program has worked fine for years and processed over a million work items.
Andomar
Wait... I thought only background threads are killed when the application that spawned them exits?
Will
@Will: I think that's the behaviour for a Windows Service. Other Windows apps work like Joel describes
Andomar
This doesn't explain why Logging.Log("Finished"); is not being called.
Kirk Broadhurst
A: 

Could your thread be dying?

Filip
+1  A: 

I have managed to make programs disappear without a trace in a similar fashion to you (no exception traces, no termination log messages) in the past. Almost all the time it was related to killing the stack (the name of this website always reminds me).

Is it possible that you are suddenly trying to process far more data than usual, or using re-entrant routines, or being 'clever' with pointers?

DISCLAIMER: my experience was with a Win32 C++ app, not C#.

IanH
+1  A: 

Could it be a memory leak? If your app takes too much memory, Windows will kill it. You can check how much memory you are using: if it grows over time, you may have a memory leak.

Another possibility is that somewhere, you have code calling Environment.Exit(). Try a full text search through your code to double-check, you never know!

redtuna
Thanks for the tips. Memory usage does not appear to grow, and the Exit() function was one of the first things we checked :)
Andomar
+2  A: 

It's possible that one of the threads that the DoWork method is spawning is throwing an exception. The default behavior in this case is for the process to terminate. You can stop this from happening by using the AppDomain.UnhandledException event to override the default behavior.

Sean Reilly
+4  A: 

Whats the identity that you're using to run the console app?

Also you might want to use SetConsoleCtrlHandler to capture the Console Events. Look at this blog for more details. We had a similar issue when the Console app was run under a service account, it would occasionally get terminated. I'm not sure if this is what you're running into. Let me know I can post some code.

UPDATE: Looks like you're scenario resembles what we had experienced. In your Console event handler, you need to check for LogOff event and return true. Look at this KB article

public static void inputHandler(ConsoleCtrl.ConsoleEvent consoleEvent)
{
   if (ConsoleEvent == ConsoleCtrl.ConsoleEvent.CtrlLogOff)
       return true; 
   return false;
}
Vasu Balakrishnan
It's being run as a scheduled task by an account with administrative privileges. I've added the handler and modified it to log events, letting it run for a while to see if it hits!
Andomar
I've added logging and the CtrlLogOff event is indeed what causes the scheduled task to exit. Problem solved, though we would still like to know where the CtrlLogOff event is coming from!
Andomar
+1  A: 

Be careful, there are some exceptions, that cannot be caught: OutOfMemoryException, StackOverflowException, therefore your program will die terribly, but silently.

Yossarian
Yeah, but I'd expect this to trigger DebugDiag and log a crash dump.
Andomar