I’d need a hand in solving today’s multithreading mystery.
I have an application that has a mediator, say:
class Mediator{
ConfigMgr * mgr;
....
Config getConfig(){
return mgr->getConfig();
};
};
ConfigMgr is properly initialized, there’s no problem with it whatsoever. It consist of, amongst other things, a Config blueprint, which is a struct that has some booleans and std::strings:
struct Config{
std::string param1;
std::string param2;
....
}
class ConfigMgr {
Config blueprint;
Config getConfig(){
Lock l(mtx); //wrapper on POSIX mutex and lock, works as expected
refreshConfig(); // some stuff that might alter Config blueprint
return config;
}
}
Finally, I have multiple working threads that once in a while might need to call
mediator->getConfig().param1;
The problem is that every now and then my app crashes with SIGABRT. From what I’ve been able to determine, it crashes on double-delete of string in Config’s destructor:
Config::~Config()
The struct has no methods written by me.
I can’t track the root cause. My Config struct is always passed by copy, not reference. I think every thread should have his own copy of Config ever since invocation of ConfigMgr::getConfig(). This construction should be thread-safe, but there clearly is some sort of race condition. Do you guys have any advice?
I’ve been hit by this. The important things to remember are:
Therefore you are hitting multiple std::strings in different threads trying to delete the same buffer, that they think should be deleted due to reference counting variables not being updated correctly.
You’re probably going to have to be more explicit about the string copies you want, and define a copy constructor for the Config object.