diff options
Diffstat (limited to 'cpp/src/qpidd.cpp')
-rw-r--r-- | cpp/src/qpidd.cpp | 106 |
1 files changed, 83 insertions, 23 deletions
diff --git a/cpp/src/qpidd.cpp b/cpp/src/qpidd.cpp index ec8fe570d3..e199c72683 100644 --- a/cpp/src/qpidd.cpp +++ b/cpp/src/qpidd.cpp @@ -19,35 +19,58 @@ * */ #include <Broker.h> -#include <signal.h> #include <iostream> #include <memory> #include <config.h> -#include <unistd.h> #include <fstream> +#include <signal.h> +#include <Daemon.h> +#include <boost/format.hpp> +using boost::format; using namespace qpid; using namespace qpid::broker; using namespace qpid::sys; using namespace std; +Broker::shared_ptr brokerPtr; + +void handle_signal(int /*signal*/){ + std::cerr << "Shutting down..." << std::endl; + brokerPtr->shutdown(); +} + + /** Command line options */ struct QpiddOptions : public Broker::Options { bool help; bool version; bool daemon; + bool quit; + bool kill; + bool check; + bool ppid; + int wait; string config; po::options_description desc; QpiddOptions() : help(false), version(false), daemon(false), + quit(false), kill(false), check(false), ppid(false), wait(10), config("/etc/qpidd.conf"), desc("Options") { using namespace po; desc.add_options() - ("daemon,d", optValue(daemon), "Run as a daemon"); + ("daemon,d", optValue(daemon), "Run as a daemon.") + ("quit,q", optValue(quit), "Stop the running daemon politely.") + ("kill,k", optValue(kill), "Kill the running daemon harshly.") + ("check,c", optValue(check), "If daemon is running return 0.") + ("wait", optValue(wait, "SECONDS"), + "Maximum wait for daemon response.") + ("ppid", optValue(ppid), "Print daemon pid to stdout" ); + po::options_description brokerOpts; Broker::Options::addTo(desc); desc.add_options() ("config", optValue(config, "FILE"), "Configuation file") @@ -87,43 +110,80 @@ ostream& operator<<(ostream& out, const QpiddOptions& config) { config.usage(out); return out; } -Broker::shared_ptr brokerPtr; - -void handle_signal(int /*signal*/){ - if (brokerPtr) { - cerr << "Shutting down..." << endl; - brokerPtr->shutdown(); - } -} - int main(int argc, char* argv[]) { QpiddOptions config; try { config.parse(argc, argv); + string name=(format("%s.%d") + % Daemon::nameFromArgv0(argv[0]) + % (config.port)).str(); + // Spelled 'demon' to avoid clash with daemon.h function. + Daemon demon(name, config.wait); + + // Options that just print information. if(config.help) { config.usage(cout); + return 0; } - else if (config.version) { + if (config.version) { cout << "qpidd (" << PACKAGE_NAME << ") version " << PACKAGE_VERSION << endl; + return 0; } - else { - brokerPtr=Broker::create(config); - signal(SIGINT, handle_signal); - if (config.daemon) { - if (daemon(0, 0) < 0) // daemon(nochdir, noclose) - throw QPID_ERROR( - INTERNAL_ERROR, - "Failed to detach as daemon: "+ strError(errno)); + + // Options that affect an already running daemon. + if (config.quit || config.kill || config.check) { + pid_t pid = demon.check(); + if (config.ppid && pid > 0) + cout << pid << endl; + if (config.kill) + demon.kill(); + else if (config.quit) + demon.quit(); + if (config.check && pid <= 0) + return 1; + return 0; + } + + // Starting the broker: + signal(SIGINT, handle_signal); + if (config.daemon) { + pid_t pid = demon.fork(); + if (pid == 0) { // Child + try { + brokerPtr=Broker::create(config); + demon.ready(); // Notify parent we're ready. + brokerPtr->run(); + } catch (const exception& e) { + // TODO aconway 2007-04-26: Log this, cerr is lost. + cerr << "Broker daemon failed: " << e.what() << endl; + demon.failed(); // Notify parent we failed. + return 1; + } } - brokerPtr->run(); + else if (pid > 0) { // Parent + if (config.ppid) + cout << pid << endl; + return 0; + } + else { // pid < 0 + throw Exception("fork failed"+strError(errno)); + } + } // Non-daemon broker. + else { + brokerPtr = Broker::create(config); + brokerPtr->run(); } return 0; } - catch(const exception& e) { + catch(const po::error& e) { + // Command line parsing error. cerr << "Error: " << e.what() << endl << "Type 'qpidd --help' for usage." << endl; } + catch(const exception& e) { + cerr << "Error: " << e.what() << endl; + } return 1; } |