diff --git a/src/cpp/ripple/Application.cpp b/src/cpp/ripple/Application.cpp index 2302c6a631..6c2ea2b178 100644 --- a/src/cpp/ripple/Application.cpp +++ b/src/cpp/ripple/Application.cpp @@ -64,6 +64,7 @@ bool Instance::running = true; void Application::stop() { cLog(lsINFO) << "Received shutdown request"; + StopSustain(); mShutdown = true; mIOService.stop(); mHashedObjectStore.bulkWrite(); diff --git a/src/cpp/ripple/main.cpp b/src/cpp/ripple/main.cpp index 320149a036..57aba443e1 100644 --- a/src/cpp/ripple/main.cpp +++ b/src/cpp/ripple/main.cpp @@ -149,6 +149,7 @@ int main(int argc, char* argv[]) ("ledger", po::value(), "Load the specified ledger and start from .") ("start", "Start from a fresh Ledger.") ("net", "Get the initial ledger from the network.") + ("fg", "Run in the foreground.") ; // Interpret positional arguments as --parameters. @@ -186,6 +187,13 @@ int main(int argc, char* argv[]) } } + if (HaveSustain() && !vm.count("parameters") && !vm.count("fg") && !vm.count("standalone")) + { + std::string logMe = DoSustain(); + if (!logMe.empty()) + Log(lsWARNING) << logMe; + } + if (vm.count("quiet")) Log::setMinSeverity(lsFATAL, true); else if (vm.count("verbose")) diff --git a/src/cpp/ripple/utils.cpp b/src/cpp/ripple/utils.cpp index 62cdebb1fa..6365a862d3 100644 --- a/src/cpp/ripple/utils.cpp +++ b/src/cpp/ripple/utils.cpp @@ -1,6 +1,8 @@ #ifdef __linux__ +#include #include +#include #endif #include @@ -373,6 +375,79 @@ extern void NameThread(const char*) { ; } #endif +#ifdef __unix__ + +static pid_t pManager = static_cast(0); +static pid_t pChild = static_cast(0); + +static void pass_signal(int a) +{ + kill(pChild, a); +} + +static void stop_manager(int) +{ + kill(pChild, SIGINT); + _exit(0); +} + +bool HaveSustain() +{ + return true; +} + +std::string StopSustain() +{ + if (getppid() != pManager) + return std::string(); + kill(pManager, SIGHUP); + return "Terminating monitor"; +} + +std::string DoSustain() +{ + int childCount = 0; + pManager = getpid(); + signal(SIGINT, stop_manager); + signal(SIGHUP, stop_manager); + signal(SIGUSR1, pass_signal); + signal(SIGUSR2, pass_signal); + while (1) + { + ++childCount; + pChild = fork(); + if (pChild == -1) + _exit(0); + if (pChild == 0) + { + NameThread("child"); + signal(SIGINT, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGUSR1, SIG_DFL); + signal(SIGUSR2, SIG_DFL); + return str(boost::format("Launching child %d") % childCount);; + } + NameThread(boost::str(boost::format("sust%d") % childCount).c_str()); + do + { + int i; + sleep(10); + waitpid(-1, &i, 0); + } + while (kill(pChild, 0) == 0); + rename("core", boost::str(boost::format("core.%d") % static_cast(pChild)).c_str()); + rename("debug.log", boost::str(boost::format("debug.log.%d") % static_cast(pChild)).c_str()); + } +} + +#else + +bool HaveSustain() { return false; } +std::string DoSustain() { return std::string; } +std::string StopSustain() { return std::string; } + +#endif + BOOST_AUTO_TEST_SUITE( Utils) BOOST_AUTO_TEST_CASE( ParseUrl ) diff --git a/src/cpp/ripple/utils.h b/src/cpp/ripple/utils.h index 8cc6014308..2c60a773f3 100644 --- a/src/cpp/ripple/utils.h +++ b/src/cpp/ripple/utils.h @@ -288,6 +288,10 @@ bool parseUrl(const std::string& strUrl, std::string& strScheme, std::string& st extern void NameThread(const char *); +extern bool HaveSustain(); +extern std::string StopSustain(); +extern std::string DoSustain(); + #if (!defined(FORCE_NO_C11X) && (__cplusplus > 201100L)) || defined(FORCE_C11X) #define C11X