summaryrefslogtreecommitdiff
path: root/cpp/src/windows/QpiddBroker.cpp
diff options
context:
space:
mode:
authorStephen D. Huston <shuston@apache.org>2009-05-18 22:21:29 +0000
committerStephen D. Huston <shuston@apache.org>2009-05-18 22:21:29 +0000
commit3680c10e6ae1759838a9381506d2d7bca1951324 (patch)
treec2451b3b48e3d506a4550c0e4816b41e4a5a2607 /cpp/src/windows/QpiddBroker.cpp
parentf211057b4402121e42ea7efbe71c179717f6e6ee (diff)
downloadqpid-python-3680c10e6ae1759838a9381506d2d7bca1951324.tar.gz
Add --quit, --check, --pid-dir options to allow shutting down a broker from command line. Needed to run test suite.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@776116 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/windows/QpiddBroker.cpp')
-rw-r--r--cpp/src/windows/QpiddBroker.cpp86
1 files changed, 84 insertions, 2 deletions
diff --git a/cpp/src/windows/QpiddBroker.cpp b/cpp/src/windows/QpiddBroker.cpp
index ffc5f700af..ed38475811 100644
--- a/cpp/src/windows/QpiddBroker.cpp
+++ b/cpp/src/windows/QpiddBroker.cpp
@@ -65,6 +65,73 @@ std::string brokerPidFile(std::string piddir, uint16_t port)
return path.str();
}
+// ShutdownEvent maintains an event that can be used to ask the broker
+// to stop. Analogous to sending SIGTERM/SIGINT to the posix broker.
+// The signal() method signals the event.
+class ShutdownEvent {
+ public:
+ ShutdownEvent(pid_t other = 0);
+ ~ShutdownEvent();
+
+ void signal();
+
+ protected:
+ std::string eventName(pid_t pid);
+ HANDLE event;
+};
+
+class ShutdownHandler : public ShutdownEvent, public qpid::sys::Runnable {
+ public:
+ ShutdownHandler(const boost::intrusive_ptr<Broker>& b)
+ : ShutdownEvent() { broker = b; }
+
+ private:
+ virtual void run(); // Inherited from Runnable
+ boost::intrusive_ptr<Broker> broker;
+};
+
+ShutdownEvent::ShutdownEvent(pid_t other) : event(NULL) {
+ // If given a pid, open an event assumedly created by that pid. If there's
+ // no pid, create a new event using the current process id.
+ if (other == 0) {
+ std::string name = eventName(GetCurrentProcessId());
+ // Auto-reset event in case multiple processes try to signal a
+ // broker that doesn't respond for some reason. Initially not signaled.
+ event = CreateEvent(NULL, false, false, name.c_str());
+ }
+ else {
+ std::string name = eventName(other);
+ event = OpenEvent(EVENT_MODIFY_STATE, false, name.c_str());
+ }
+ QPID_WINDOWS_CHECK_NULL(event);
+}
+
+ShutdownEvent::~ShutdownEvent() {
+ CloseHandle(event);
+ event = NULL;
+}
+
+void ShutdownEvent::signal() {
+ QPID_WINDOWS_CHECK_NOT(SetEvent(event), 0);
+}
+
+std::string ShutdownEvent::eventName(pid_t pid) {
+ std::ostringstream name;
+ name << "qpidd_" << pid << std::ends;
+ return name.str();
+}
+
+
+void ShutdownHandler::run() {
+ if (event == NULL)
+ return;
+ WaitForSingleObject(event, INFINITE);
+ if (broker.get()) {
+ broker->shutdown();
+ broker = 0; // Release the broker reference
+ }
+}
+
}
struct ProcessControlOptions : public qpid::Options {
@@ -139,8 +206,14 @@ int QpiddBroker::execute (QpiddOptions *options) {
return 1;
if (myOptions->control.check)
std::cout << pid << std::endl;
- if (myOptions->control.quit)
- std::cout << "Need to stop pid " << pid << std::endl;
+ if (myOptions->control.quit) {
+ ShutdownEvent shutter(pid);
+ HANDLE brokerHandle = OpenProcess(SYNCHRONIZE, false, pid);
+ QPID_WINDOWS_CHECK_NULL(brokerHandle);
+ shutter.signal();
+ WaitForSingleObject(brokerHandle, INFINITE);
+ CloseHandle(brokerHandle);
+ }
return 0;
}
@@ -153,6 +226,15 @@ int QpiddBroker::execute (QpiddOptions *options) {
options->broker.port),
true);
myPid.writePid();
+
+ // Allow the broker to receive a shutdown request via a qpidd --quit
+ // command. Note that when the broker is run as a service this operation
+ // should not be allowed.
+
+ ShutdownHandler waitShut(brokerPtr);
+ qpid::sys::Thread waitThr(waitShut); // Wait for shutdown event
brokerPtr->run();
+ waitShut.signal(); // In case we shut down some other way
+ waitThr.join();
return 0;
}