You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I found this problem in my job, to reproduce that problem, the simplified model is as follows:
int echo()
{
return 0;
}
TEST(ProcStubTest, test1)
{
MOCKER(echo)
.stubs()
.will(invoke(+[]{
return 1;
}));
std::vector<std::thread> thds;
for ( int i = 0; i < 4; i++ )
{
thds.emplace_back([]{
for ( int i = 0; i < 100; i++ )
{
EXPECT_EQ(1, echo());
}
});
}
for ( auto&& t : thds )
{
t.join();
}
GlobalMockObject::verify();
}
problem:
when invoke the function be mocked concurrently,the operator= of result (member of ProcStub object) will be invoked concurrently, however, it's not thread safe, may cause double free/accessing freed memory etc..
In order to test my conclusion, I add a mutex for ProcStub as follows:
MOCKCPP_NS_START
template <typename F>
struct ThreadSafeProcStub;
#define THREAD_SAFE_PROC_STUB(n) \
template <typename R DECL_TEMPLATE_ARGS(n)> \
struct ThreadSafeProcStub<R(DECL_ARGS(n))> : public ProcStubBase \
{ \
public: \
typedef R (*Func)(DECL_ARGS(n)); \
ThreadSafeProcStub(Func f, std::string name) : ProcStubBase(name, (void*)f), func(f){}\
Any& invoke(const Invocation& inv) \
{ \
SIMPLE_REPEAT(n, MOCKCPP_CHECK_AND_ASSIGN_PARAMETER); \
Any tmp = func(DECL_PARAMS(n)); \
std::lock_guard<std::mutex> lck{mtx}; \
results.emplace_back(tmp); \
return results.back(); \
} \
private: \
Func func; \
std::mutex mtx; \
std::list<Any> results; \
}; \
template <typename R DECL_TEMPLATE_ARGS(n)> \
Stub* invoke_thread_safe(R(*f)(DECL_ARGS(n)), const char* name = 0) \
{ \
return new ThreadSafeProcStub<R(DECL_ARGS(n))>(f, name ? name : ""); \
}
THREAD_SAFE_PROC_STUB(0);
THREAD_SAFE_PROC_STUB(1);
THREAD_SAFE_PROC_STUB(2);
THREAD_SAFE_PROC_STUB(3);
THREAD_SAFE_PROC_STUB(4);
THREAD_SAFE_PROC_STUB(5);
THREAD_SAFE_PROC_STUB(6);
THREAD_SAFE_PROC_STUB(7);
THREAD_SAFE_PROC_STUB(8);
THREAD_SAFE_PROC_STUB(9);
THREAD_SAFE_PROC_STUB(10);
THREAD_SAFE_PROC_STUB(11);
THREAD_SAFE_PROC_STUB(12);
MOCKCPP_NS_END
int echo()
{
return 0;
}
TEST(ProcStubTest, test1)
{
MOCKER(echo)
.stubs()
.will(invoke_thread_safe(+[]{
return 1;
}));
std::vector<std::thread> thds;
for ( int i = 0; i < 4; i++ )
{
thds.emplace_back([]{
for ( int i = 0; i < 100; i++ )
{
EXPECT_EQ(1, echo());
}
});
}
for ( auto&& t : thds )
{
t.join();
}
GlobalMockObject::verify();
}
It seems works and no longer cause coredump(although the implementation may not be so graceful).
The text was updated successfully, but these errors were encountered:
I found this problem in my job, to reproduce that problem, the simplified model is as follows:
problem:
when invoke the function be mocked concurrently,the operator= of result (member of ProcStub object) will be invoked concurrently, however, it's not thread safe, may cause double free/accessing freed memory etc..
In order to test my conclusion, I add a mutex for ProcStub as follows:
It seems works and no longer cause coredump(although the implementation may not be so graceful).
The text was updated successfully, but these errors were encountered: