but has returned an error response (which is included in the message). The
NOTIFY request will not be honored.
-% AUTH_DATASRC_CLIENT_BUILDER_STARTED data source builder thread started
+% AUTH_DATASRC_CLIENTS_BUILDER_STARTED data source builder thread started
-% AUTH_DATASRC_CLIENT_BUILDER_STOPPED data source builder thread stopped
+% AUTH_DATASRC_CLIENTS_BUILDER_STOPPED data source builder thread stopped
-% AUTH_DATASRC_CLIENT_BUILDER_COMMAND data source builder received command, ID: %1
+% AUTH_DATASRC_CLIENTS_BUILDER_COMMAND data source builder received command, ID: %1
+
+% AUTH_DATASRC_CLIENTS_MANAGER_UNEXPECTED_STOP data source clients manager stopped unexpectedly, leaving the builder thread
#include <auth/auth_log.h>
#include <boost/bind.hpp>
+#include <boost/scoped_ptr.hpp>
#include <list>
#include <utility>
public:
DataSrcClientsMgrBase() :
builder_(&command_queue_, &cond_, &queue_mutex_),
- builder_thread_(boost::bind(&BuilderType::run, &builder_))
+ builder_thread_(new ThreadType(boost::bind(&BuilderType::run,
+ &builder_)))
{}
- ~DataSrcClientsMgrBase() {}
+ ~DataSrcClientsMgrBase() {
+ if (builder_thread_) {
+ // An unexpected case. The manager is being destroyed without
+ // a prior shutdown(). We notify the builder to minimize the risk
+ // of leaving it as a zombie, but doesn't wait to avoid hangup.
+ LOG_INFO(auth_logger, AUTH_DATASRC_CLIENTS_MANAGER_UNEXPECTED_STOP);
+ sendCommand(internal::SHUTDOWN, data::ConstElementPtr());
+ }
+ }
void shutdown() {
sendCommand(internal::SHUTDOWN, data::ConstElementPtr());
- builder_thread_.wait();
+ builder_thread_->wait();
+ builder_thread_.reset();
}
private:
CondVarType cond_;
MutexType queue_mutex_;
BuilderType builder_;
- ThreadType builder_thread_;
+ boost::scoped_ptr<ThreadType> builder_thread_;
};
namespace internal {
template <typename MutexType, typename CondVarType>
void
DataSrcClientsBuilderBase<MutexType, CondVarType>::run() {
- LOG_INFO(auth_logger, AUTH_DATASRC_CLIENT_BUILDER_STARTED);
+ LOG_INFO(auth_logger, AUTH_DATASRC_CLIENTS_BUILDER_STARTED);
bool keep_running = true;
while (keep_running) {
}
}
- LOG_INFO(auth_logger, AUTH_DATASRC_CLIENT_BUILDER_STOPPED);
+ LOG_INFO(auth_logger, AUTH_DATASRC_CLIENTS_BUILDER_STOPPED);
}
template <typename MutexType, typename CondVarType>
const Command& command)
{
LOG_DEBUG(auth_logger, DBGLVL_TRACE_BASIC,
- AUTH_DATASRC_CLIENT_BUILDER_COMMAND).arg(command.first);
+ AUTH_DATASRC_CLIENTS_BUILDER_COMMAND).arg(command.first);
switch (command.first) {
case SHUTDOWN:
using namespace isc::auth::internal;
namespace {
+void
+shutdownCheck() {
+ // Check for common points on shutdown. The manager should have acquired
+ // the lock, put a SHUTDOWN command to the queue, and should have signaled
+ // the builder.
+ EXPECT_EQ(1, FakeDataSrcClientsBuilder::queue_mutex->lock_count);
+ EXPECT_EQ(1, FakeDataSrcClientsBuilder::cond->signal_count);
+ EXPECT_EQ(1, FakeDataSrcClientsBuilder::command_queue->size());
+ const Command& cmd = FakeDataSrcClientsBuilder::command_queue->front();
+ EXPECT_EQ(SHUTDOWN, cmd.first);
+ EXPECT_FALSE(cmd.second); // no argument
+}
+
TEST(DataSrcClientsMgrTest, start) {
// When we create a manager, builder's run() method should be called.
FakeDataSrcClientsBuilder::started = false;
- TestDataSrcClientsMgr mgr;
- EXPECT_TRUE(FakeDataSrcClientsBuilder::started);
- EXPECT_TRUE(FakeDataSrcClientsBuilder::command_queue->empty());
+ {
+ TestDataSrcClientsMgr mgr;
+ EXPECT_TRUE(FakeDataSrcClientsBuilder::started);
+ EXPECT_TRUE(FakeDataSrcClientsBuilder::command_queue->empty());
+ }
+
+ // We stopped the manager implicitly (without shutdown()). In this case
+ // the builder should be notified but the manager didn't wait.
+ shutdownCheck();
+ EXPECT_FALSE(FakeDataSrcClientsBuilder::thread_waited);
}
TEST(DataSrcClientsMgrTest, shutdown) {
EXPECT_FALSE(FakeDataSrcClientsBuilder::thread_waited);
mgr.shutdown();
-
- // The manager should have acquired the lock, put a SHUTDOWN command
- // to the queue, and should have signaled the builder.
- EXPECT_EQ(1, FakeDataSrcClientsBuilder::queue_mutex->lock_count);
- EXPECT_EQ(1, FakeDataSrcClientsBuilder::cond->signal_count);
- EXPECT_EQ(1, FakeDataSrcClientsBuilder::command_queue->size());
- const Command& cmd = FakeDataSrcClientsBuilder::command_queue->front();
- EXPECT_EQ(SHUTDOWN, cmd.first);
- EXPECT_FALSE(cmd.second);
+ shutdownCheck();
EXPECT_TRUE(FakeDataSrcClientsBuilder::thread_waited);
}