summaryrefslogtreecommitdiff
path: root/cpp/src/qpid
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2007-06-11 16:05:06 +0000
committerAlan Conway <aconway@apache.org>2007-06-11 16:05:06 +0000
commitb59a0092f12a07f925bc0b1c7f8cf4949dd374e7 (patch)
treec6c188962552bac59bb96b8b7b00d791ae9e4be1 /cpp/src/qpid
parent4c88e1be1c96cf27b8418df2a60c3cbbefd92fcc (diff)
downloadqpid-python-b59a0092f12a07f925bc0b1c7f8cf4949dd374e7.tar.gz
QPID-504: Print bound port if --port 0 is specified. Not yet used by tests.
* qpidd.cpp: - With --port 0 print the bound port number to stdout. - Removed --ppid, --check now prints pid. * Daemon.cpp/h: Move pid-file generation to caller (qpidd.cpp) * Exception.cpp: Log a debug message in exception constructors. Helps to show what exceptions were thrown even if they aren't logged at a higher level. * daemon_test: Test new daemon options. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@546180 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid')
-rw-r--r--cpp/src/qpid/Exception.cpp13
-rw-r--r--cpp/src/qpid/broker/Daemon.cpp99
-rw-r--r--cpp/src/qpid/broker/Daemon.h50
3 files changed, 90 insertions, 72 deletions
diff --git a/cpp/src/qpid/Exception.cpp b/cpp/src/qpid/Exception.cpp
index e73f64f2ba..f4eeb7931b 100644
--- a/cpp/src/qpid/Exception.cpp
+++ b/cpp/src/qpid/Exception.cpp
@@ -19,7 +19,9 @@
*
*/
+#include "qpid/log/Statement.h"
#include "Exception.h"
+#include <typeinfo>
#include <errno.h>
namespace qpid {
@@ -28,12 +30,17 @@ std::string strError(int err) {
char buf[512];
return std::string(strerror_r(err, buf, sizeof(buf)));
}
+
+static void ctorLog(const std::exception* e) {
+ QPID_LOG(trace, "Exception constructor " << typeid(e).name() << ": " << e->what());
+}
-Exception::Exception() throw() {}
+Exception::Exception() throw() { ctorLog(this); }
-Exception::Exception(const std::string& str) throw() : whatStr(str) {}
+Exception::Exception(const std::string& str) throw()
+ : whatStr(str) { ctorLog(this); }
-Exception::Exception(const char* str) throw() : whatStr(str) {}
+Exception::Exception(const char* str) throw() : whatStr(str) { ctorLog(this); }
Exception::~Exception() throw() {}
diff --git a/cpp/src/qpid/broker/Daemon.cpp b/cpp/src/qpid/broker/Daemon.cpp
index 3c5a642b60..2b64e7761b 100644
--- a/cpp/src/qpid/broker/Daemon.cpp
+++ b/cpp/src/qpid/broker/Daemon.cpp
@@ -16,50 +16,35 @@
*
*/
#include "Daemon.h"
+#include "qpid/log/Statement.h"
#include "qpid/QpidError.h"
#include <libdaemon/daemon.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <signal.h>
-#include <boost/filesystem/path.hpp>
-#include <boost/filesystem/operations.hpp>
namespace qpid {
namespace broker {
using namespace std;
-string Daemon::pidFile;
-string Daemon::name;
+boost::function<std::string()> qpid::broker::Daemon::pidFileFn;
-string Daemon::nameFromArgv0(const char* argv0) {
- return string(daemon_ident_from_argv0(const_cast<char*>(argv0)));
+std::string Daemon::defaultPidFile(const std::string& identifier) {
+ daemon_pid_file_ident=identifier.c_str();
+ return daemon_pid_file_proc_default();
}
-const char* Daemon::getPidFile() {
- if (pidFile.empty()) {
- const char* home=getenv("HOME");
- if (!home)
- throw(Exception("$HOME is not set, cant create $HOME/.qpidd."));
- using namespace boost::filesystem;
- path dir = path(home,native) / path(".qpidd", native);
- create_directory(dir);
- dir /= name;
- pidFile = dir.string();
- }
- return pidFile.c_str();
+const char* Daemon::realPidFileFn() {
+ static std::string str = pidFileFn();
+ return str.c_str();
}
-Daemon::Daemon(const string& name_, int secs) : pid(-1), timeout(secs)
+Daemon::Daemon(boost::function<std::string()> fn, int secs) : pid(-1), timeout(secs)
{
- name = name_;
- daemon_pid_file_ident = daemon_log_ident = name.c_str();
- if (getuid() != 0) {
- // For normal users put pid file under $HOME/.qpid
- daemon_pid_file_proc = getPidFile;
- }
- // For root use the libdaemon default: /var/run.
+ pidFileFn = fn;
+ daemon_pid_file_proc = &realPidFileFn;
}
Daemon::~Daemon() {
@@ -77,44 +62,58 @@ class Daemon::Retval {
bool completed;
};
-pid_t Daemon::fork() {
+pid_t Daemon::fork(Function parent, Function child) {
retval.reset(new Retval());
pid = daemon_fork();
if (pid < 0)
- throw Exception("Failed to fork daemon: "+strError(errno));
- else if (pid > 0) {
- int ret = retval->wait(timeout); // parent, wait for child.
- if (ret != 0) {
- string err;
- if (ret > 0)
- err = strError(ret);
- else if (ret == -1)
- err= strError(errno);
- else
- err= "unknown error";
- throw Exception("Deamon startup failed: "+err);
+ throw Exception("Failed to fork daemon: "+strError(errno));
+ else if (pid == 0) {
+ try {
+ child(*this);
+ } catch (const exception& e) {
+ QPID_LOG(debug, "Rethrowing: " << e.what());
+ failed(); // Notify parent
+ throw;
}
}
- else if (pid == 0) { // child.
- // TODO aconway 2007-04-26: Should log failures.
- if (daemon_pid_file_create())
- failed();
- }
+ else
+ parent(*this);
return pid;
}
-void Daemon::notify(int i) {
+int Daemon::wait() { // parent
+ assert(retval);
+ errno = 0; // Clear errno.
+ int ret = retval->wait(timeout); // wait for child.
+ if (ret == -1) {
+ if (errno)
+ throw Exception("Error waiting for daemon startup:"
+ +strError(errno));
+ else
+ throw Exception("Error waiting for daemon startup, check logs.");
+ }
+ return ret;
+}
+
+void Daemon::notify(int value) { // child
assert(retval);
- if (retval->send(i))
+ if (retval->send(value))
throw Exception("Failed to notify parent: "+strError(errno));
}
-void Daemon::ready() { notify(0); }
+void Daemon::ready(int value) { // child
+ if (value==-1)
+ throw Exception("Invalid value in Dameon::notify");
+ errno = 0;
+ if (daemon_pid_file_create() != 0)
+ throw Exception(string("Failed to create PID file ") +
+ daemon_pid_file_proc()+": "+strError(errno));
+ notify(value);
+}
-// NB: Not -1, confused with failure of fork() on the parent side.
-void Daemon::failed() { notify(errno? errno:-2); }
+void Daemon::failed() { notify(-1); }
-void Daemon::quit() {
+void Daemon::quit() {
if (daemon_pid_file_kill_wait(SIGINT, timeout))
throw Exception("Failed to stop daemon: " + strError(errno));
}
diff --git a/cpp/src/qpid/broker/Daemon.h b/cpp/src/qpid/broker/Daemon.h
index cf9bf13764..cf7ad37b3a 100644
--- a/cpp/src/qpid/broker/Daemon.h
+++ b/cpp/src/qpid/broker/Daemon.h
@@ -21,6 +21,7 @@
#include <string>
#include <boost/scoped_ptr.hpp>
+#include <boost/function.hpp>
namespace qpid {
namespace broker {
@@ -32,24 +33,39 @@ namespace broker {
class Daemon
{
public:
-
- /** Extract the daemon's name from argv[0] */
- static std::string nameFromArgv0(const char* argv0);
+ /** Utility function to create pid file name in a standard place
+ * (may require root acces) using identifier as the file name.
+ */
+ static std::string defaultPidFile(const std::string& identifier);
/**
- * Creating a Daemon instance forks a daemon process.
- *@param name used to create pid files etc.
- *@param timeout in seconds for all operations that wait.
+ * Daemon control object.
+ *@param pidFileFn Function that will comupte a PID file name.
+ * Called when pid file is created in ready()
+ *@param timeout in seconds for any operations that wait.
*/
- Daemon(const std::string& name, int timeout);
+ Daemon(boost::function<std::string()> pidFileFn, int timeout);
~Daemon();
-
- /** Fork the daemon, wait till it signals readiness */
- pid_t fork();
- /** Child only, send ready signal so parent fork() will return. */
- void ready();
+ typedef boost::function<void(Daemon&)> Function;
+
+ /** Fork the daemon.
+ *@param parent called in the parent process.
+ *@param child called in the child process.
+ */
+ pid_t fork(Function parent, Function child);
+
+ /** Parent only: wait for child to indicate it is ready.
+ * @return value child passed to ready() */
+ int wait();
+
+ /** Child only. Notify the parent we are ready and write the
+ * PID file.
+ *@param value returned by parent call to wait(). -1 is reserved
+ * for signalling an error.
+ */
+ void ready(int value);
/** Child only, send failed signal so parent fork() will throw. */
void failed();
@@ -67,18 +83,16 @@ class Daemon
bool isChild() { return pid == 0; }
- std::string getName() const { return name; }
-
pid_t getPid() const {return pid; }
private:
class Retval;
+ static boost::function<std::string()> pidFileFn;
+ static const char* realPidFileFn();
void notify(int);
- static std::string name;
- static std::string pidFile;
- static const char* getPidFile();
+ static std::string identifier;
boost::scoped_ptr<Retval> retval;
pid_t pid;
int timeout;
@@ -86,6 +100,4 @@ class Daemon
}} // namespace qpid::broker
-
-
#endif /*!_broker_Daemon_h*/