#include #include #include #include #include "../shared/MiscSupport.h" #include "../shared/SimpleLogFile.h" #include "../shared/GlobalConfigFile.h" #include "../shared/MarketHours.h" #include "MainLoop.h" static bool signalReceived = false; static void signalHandler(int signal) { // Spryware needs to do its cleanup. Most of the code is fine with being // terminated. std::cout<<"Cleaning up. Please wait."<= endTime) || signalReceived) // Note: It could take us up to 1 second to deal with a signal. But // since the cleanup routine takes several seconds, that shouldn't // matter. In reality it could take much longer. Since we're trying // to insert something into the data node thead, we have to wait for // whatever's going on in there. If something's locked up, we can't // do a graceful shutdown. If we're in the process of a normal start, // it could take a while to get to this message. Also, there's a known // issue in SpryWare, and if we try to shut down the PricePlus table // before it has finished initializing, things will lock up. break; if (now > startTime) { // Start full alerts. start(); // Don't call this again! startTime = std::numeric_limits< time_t >::max(); } sleep(1); } msg.clear(); msg<<__FILE__<<__LINE__<<__FUNCTION__ <<"exiting now"; sendToLogFile(msg); requestGracefulShutdown(); // Graceful exit hangs a lot! Wait three minutes before trying a hard exit. // Hard exit always works, as long as someone else does the clean up before // trying to start again. Leaving these things running for more than a day // would probably be a bad idea. I chose 20 minutes because Curtiss from // SpryWare said that sometimes it takes 15 minutes to shut down. He said // that's part of a bug that he hopes to fix soon. (Info received // 11/20/2009) It takes only a few seconds when it works correctly. endTime = time(NULL) + 20 * MARKET_HOURS_MINUTE; // Wait for the graceful shutdown, including waiting for the log file to // process that last message. Then someone will call exit(). // Even if we weren't deferring to another thread, we'd still call exit() // rather than just falling through the bottom of main(). // Some of these local objects don't shut down very well. It's better to // call exit() than to just fall through. Also, this only works because // the SpryWare code is doing it's cleanup. If you comment that code out, // and try to fall through the end of main(), things will fail badly. while (time(NULL) < endTime) sleep(1); msg.clear(); msg<<__FILE__<<__LINE__<<__FUNCTION__ <<"hard exit now"<<"graceful exit timed out"; sendToLogFile(msg); startHardShutdown(); startHardShutdown(); // Again, we can't fall through. That would cause errors and our log file // would not be right. while (true) sleep(10000); }