Browse Source

[5208a] hook points can be registered several times

 - see ticket #5251 for explanation of the problem
Tomek Mrugalski 8 years ago
parent
commit
35f04448ae

+ 16 - 2
src/lib/hooks/server_hooks.cc

@@ -46,10 +46,24 @@ ServerHooks::registerHook(const string& name) {
         hooks_.insert(make_pair(name, index));
 
     if (!result.second) {
+
+        // There's a problem with hook libraries that need to be linked with
+        // libdhcpsrv. For example host_cmds hook library requires host
+        // parser, so it needs to be linked with libdhcpsrv. However, when
+        // unit-tests are started, the hook points are not registered.
+        // When the library is loaded new hook points are registered.
+        // This causes issues in the hooks framework, especially when
+        // LibraryManager::unloadLibrary() iterates through all hooks
+        // and then calls deregisterAllCallouts. This method gets
+        // hook_index that is greater than number of elements in
+        // hook_vector_ and then we have a read past the array boundary.
+        /// @todo: See ticket 5251 and 5208 for details.
+        return (getIndex(name));
+
         // New element was not inserted because an element with the same name
         // already existed.
-        isc_throw(DuplicateHook, "hook with name " << name <<
-                  " is already registered");
+        //isc_throw(DuplicateHook, "hook with name " << name <<
+        //         " is already registered");
     }
 
     // Element was inserted, so add to the inverse hooks collection.

+ 8 - 3
src/lib/hooks/tests/hooks_manager_unittest.cc

@@ -431,7 +431,7 @@ TEST_F(HooksManagerTest, PrePostCalloutShared) {
 
     HooksManager::callCallouts(hookpt_two_index_, *handle);
 
-    // Expect same value i.e. 1027 * 2 
+    // Expect same value i.e. 1027 * 2
     result = 0;
     handle->getArgument("result", result);
     EXPECT_EQ(2054, result);
@@ -564,8 +564,13 @@ TEST_F(HooksManagerTest, RegisterHooks) {
     EXPECT_EQ(2, HooksManager::registerHook(string("alpha")));
     EXPECT_EQ(3, HooksManager::registerHook(string("beta")));
     EXPECT_EQ(4, HooksManager::registerHook(string("gamma")));
-    EXPECT_THROW(static_cast<void>(HooksManager::registerHook(string("alpha"))),
-                 DuplicateHook);
+
+
+    // The code used to throw, but it now allows to register the same
+    // hook several times. It simply returns existing index.
+    //EXPECT_THROW(static_cast<void>(HooksManager::registerHook(string("alpha"))),
+    //             DuplicateHook);
+    EXPECT_EQ(2, HooksManager::registerHook(string("alpha")));
 
     // ... an check the hooks are as we expect.
     EXPECT_EQ(5, ServerHooks::getServerHooks().getCount());

+ 26 - 2
src/lib/hooks/tests/server_hooks_unittest.cc

@@ -54,8 +54,9 @@ TEST(ServerHooksTest, RegisterHooks) {
 }
 
 // Check that duplicate names cannot be registered.
-
-TEST(ServerHooksTest, DuplicateHooks) {
+// This test has been updated. See #5251 for details. The old
+// code is retained in case we decide to get back to it.
+TEST(ServerHooksTest, DISABLED_OldDuplicateHooks) {
     ServerHooks& hooks = ServerHooks::getServerHooks();
     hooks.reset();
 
@@ -68,6 +69,29 @@ TEST(ServerHooksTest, DuplicateHooks) {
     EXPECT_THROW(hooks.registerHook("gamma"), DuplicateHook);
 }
 
+// Check that duplicate names are handled properly. The code used to throw,
+// but it now returns the existing index. See #5251 for details.
+TEST(ServerHooksTest, NewDuplicateHooks) {
+    ServerHooks& hooks = ServerHooks::getServerHooks();
+    hooks.reset();
+
+    int index = hooks.getIndex("context_create");
+
+    // Ensure we can duplicate one of the existing names.
+    // Instead of throwing, we just check that a resonable
+    // index has been returned.
+    EXPECT_EQ(index, hooks.registerHook("context_create"));
+
+    // Check that mutiple attempts to register the same hook will return
+    // existing index.
+    int gamma = hooks.registerHook("gamma");
+    EXPECT_EQ(2, gamma);
+    EXPECT_EQ(gamma, hooks.registerHook("gamma"));
+    EXPECT_EQ(gamma, hooks.registerHook("gamma"));
+    EXPECT_EQ(gamma, hooks.registerHook("gamma"));
+    EXPECT_EQ(gamma, hooks.registerHook("gamma"));
+}
+
 // Checks that we can get the name of the hooks.
 
 TEST(ServerHooksTest, GetHookNames) {