tags:

views:

832

answers:

3

How can I execute some code when my process is going to exit? I've tried this:

public static void Main(string[] args) {

    StartUpMyServer();

    AppDomain.CurrentDomain.ProcessExit += delegate(object sender, EventArgs e)
    {
        Console.WriteLine("process exiting!");
        TellMyServerToStopAcceptingConnectionsAndWaitUntilItsFinishedWithAnyExistingOnes();
    };

    Thread.Sleep(Timeout.Infinite);

}

"process exiting" is never printed and nothing else seems to happen.

Whatever it is, it needs to be cross-platform (Mono/Linux/OS X/Windows).

Thanks!

Clarification: I could probably accomplish what I want to do by starting and stopping the server on a separate thread and polling a 'stop requested' flag (which would be set in the ProcessExit event hander) on the main thread every X ms. I'd like to avoid this solution if possible (extra thread, cpu cycles). I just want to main thread to suspend until such time as the process is exiting, when it should tell the server to stop. Possible?

+2  A: 

Your Thread.Sleep is blocking. You will have to think of a better idea. Without knowledge how your server runs, I cant help.

leppie
I thought that might have been the case. So that event comes in on the main thread after the Main function exits? Or...?
bvanderveen
+1  A: 

Implement IDisposable on the objects that need cleanup, and Dispose() them as the application/server shuts down. It'll automatically proceed after everything is a happy walnut. :)

280Z28
The only 'cleanup' that's required in this case is calling that method on the server, which isn't cleanup so much as just letting it finish what it's doing before the process dies.
bvanderveen
+1  A: 

I have encountered a similar problem. Where I work, we have a set of libraries that get used by every client-side application we write, which contains cleanup code that needs to be executed upon application exit. AppDomain.CurrentDomain.ProcessExit works great for us, and we have to use that method because we can't rely on the top-level application (running Program.Main) to explicitly call our cleanup method, nor do we have any control over that (since it's not our code, it belongs to the user using our libraries).

However... in your situation, I don't think you need to worry about a ProcessExit event to fire your cleanup code. You're writing some sort of network server, hosted in a console application. How about:

public static void Main(string[] args)
{
  StartUpMyServer();

  Console.WriteLine("Press the ESCAPE key to shut down the server.");
  while (Console.ReadKey(true).Key != ConsoleKey.Escape);

  ShutDownMyServer();
}

Then when the user presses ESCAPE, your server will be shut down. The really elegant way to do this for a networked server would be to create a Windows service, which will give you handy OnStart() and OnStop() methods, where you just include your appropriate start-up and shut-down code, and the Windows service manager handles calling those for you. Ultimately, the real problem is ensuring that you're not sleeping forever... you need some way to signal your application to exit. There are many ways to do it, it all depends on how you're intending your app to run.

Brad
Close, but really I need to be able to be able to respond to SIGHUP/kill or similar (in a cross-platform way). In my case, this process is being started and stopped by another process, using System.Diagnostics.Process.
bvanderveen
Did some digging and it seems like creating a Windows service is the best way to go. Unfortunately however, mono's service support (mono-service) doesn't allow you to pass command-line arguments to your service! I'm going to see if I can't submit a patch sometime this week or weekend. Thanks for the tip.
bvanderveen