Proper way to shut down console app.
Posted: Wed Dec 10, 2014 7:53 am
Greetings all, been a while since I've been on the forum but I'm still working away at my Ogre game.
I'm just starting to work on a server. I'm building it as just a plain VC9 console application because I want it to be as threadbare as possible, and I figured a console would be nice and simple.
However I seem to have run into a very weird and fundamental property of consoles which makes me wonder how the hell anyone ever got them to do anything useful in the first place.
The problem is that at any moment someone might close the console, by for instance simply clicking the 'X' box in the top right corner, or other methods. When this happens, I need to do a proper shutdown, to unload things, to send messages to all the players that the console is closing down. But damned if I can find a reliable way to do that.
Basically there seem to be two main methods I've read.
The first is to use the atexit(SomeFunction) function. In theory this will call SomeFunction() when the console closes. But I have found it to be incredibly difficult to use and unreliable. dlls are already unloaded by the time the function is called. Other functions can mess it up (for instance, I use easylogging++, a header only logger, and if I use any easylogging++ functions in the exit function, the exit function seems to just be ignored.
I've also seen that atexit() often fails if the main loop is busy. So the more processing going on in the mainloop, the more likely atexit will simply do nothing. I tested this by printing some stuff to the console in the mainloop, at the same time as closing the app. Print too much, and atexit seems to get skipped.
The second method is to use SetConsoleCtrlHandler and receive the shutdown messages and do the shutdown in the handler. But this is just as big a minefield, since the handler is launched in it's own thread, meaning for a moment both the standard code and the shutdown code can be running simultaneously. So I might be trying to shutdown and free some memory or object at the same time the server is trying to perform normal processing on that memory.
Ugh. Seems like a ridiculous nightmare. How do I cleanup when a console gets shut down by the user in an unexpected way?
Edit: Tried something with the SetConsoleCtrlHandler method. Put a mutex around the handler and a mutex in the mainloops, so in theory only one of them can run at a time. Result is that sometimes it works, sometimes it doesn't, same as before. In otherwords, sometimes the shutdown code gets executed, sometimes it simply gets skipped.
I'm just starting to work on a server. I'm building it as just a plain VC9 console application because I want it to be as threadbare as possible, and I figured a console would be nice and simple.
However I seem to have run into a very weird and fundamental property of consoles which makes me wonder how the hell anyone ever got them to do anything useful in the first place.
The problem is that at any moment someone might close the console, by for instance simply clicking the 'X' box in the top right corner, or other methods. When this happens, I need to do a proper shutdown, to unload things, to send messages to all the players that the console is closing down. But damned if I can find a reliable way to do that.
Basically there seem to be two main methods I've read.
The first is to use the atexit(SomeFunction) function. In theory this will call SomeFunction() when the console closes. But I have found it to be incredibly difficult to use and unreliable. dlls are already unloaded by the time the function is called. Other functions can mess it up (for instance, I use easylogging++, a header only logger, and if I use any easylogging++ functions in the exit function, the exit function seems to just be ignored.
I've also seen that atexit() often fails if the main loop is busy. So the more processing going on in the mainloop, the more likely atexit will simply do nothing. I tested this by printing some stuff to the console in the mainloop, at the same time as closing the app. Print too much, and atexit seems to get skipped.
The second method is to use SetConsoleCtrlHandler and receive the shutdown messages and do the shutdown in the handler. But this is just as big a minefield, since the handler is launched in it's own thread, meaning for a moment both the standard code and the shutdown code can be running simultaneously. So I might be trying to shutdown and free some memory or object at the same time the server is trying to perform normal processing on that memory.
Ugh. Seems like a ridiculous nightmare. How do I cleanup when a console gets shut down by the user in an unexpected way?
Edit: Tried something with the SetConsoleCtrlHandler method. Put a mutex around the handler and a mutex in the mainloops, so in theory only one of them can run at a time. Result is that sometimes it works, sometimes it doesn't, same as before. In otherwords, sometimes the shutdown code gets executed, sometimes it simply gets skipped.