Skip to content

Commit

Permalink
Correct invalid deferred destruction
Browse files Browse the repository at this point in the history
In the case of an injection race, the thread that loses the race must immediately tear down the object which was not successfully injected.  Fix this bug and guard with a new test.
  • Loading branch information
codemercenary committed Apr 16, 2016
1 parent 87df97c commit aad3d20
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/autowiring/CoreContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,10 @@ class CoreContext:
return memo.m_value.template as<T>();
}

// Need the memo for the actual type at this point, if we don't hold this down then this
// entry might not get constructed.
auto& memo = FindByType(auto_id_t<typename CreationRules::TActual>{}, true);

// We must make ourselves current for the remainder of this call:
CurrentContextPusher pshr(shared_from_this());
std::shared_ptr<typename CreationRules::TActual> retVal(
Expand All @@ -613,7 +617,6 @@ class CoreContext:
// we will simply eat this exception, and handle it silently by returning the type that
// someone else has already attempted to construct, as per the documented behavior of
// Construct.
auto& memo = FindByType(auto_id_t<typename CreationRules::TActual>{}, true);
retVal = memo.m_value.template as<typename CreationRules::TActual>();
}

Expand Down
44 changes: 44 additions & 0 deletions src/autowiring/test/CoreContextTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,3 +636,47 @@ TEST_F(CoreContextTest, AwaitTimed) {

injector.join();
}

namespace {
class HoldsMutexAndCount {
public:
int initCount = 0;
int instanceCount = 0;
std::mutex lk;
};

class DelaysWithNwa {
public:
DelaysWithNwa(void) {
std::lock_guard<std::mutex>{ hmac->lk };

hmac->initCount++;
hmac->instanceCount++;
}

virtual ~DelaysWithNwa(void) {
hmac->instanceCount--;
}

AutoRequired<HoldsMutexAndCount> hmac;
};
}

TEST_F(CoreContextTest, SimultaneousMultiInject) {
AutoCreateContext ctxt;
AutoRequired<HoldsMutexAndCount> hmac{ ctxt };

std::unique_lock<std::mutex> lk{ hmac->lk };
std::thread a([ctxt] { ctxt->Inject<DelaysWithNwa>(); });
std::thread b([ctxt] { ctxt->Inject<DelaysWithNwa>(); });
lk.unlock();

a.join();
b.join();

// Two initializations should have taken place due to the barrier
ASSERT_EQ(2, hmac->initCount);

// Only one of those two instances should still be around
ASSERT_EQ(1, hmac->instanceCount);
}

0 comments on commit aad3d20

Please sign in to comment.