A few days ago my friend told me about the situation, they had in their project.
Someone decided, that it would be good to destroy the object of NotVerySafeClass in parallel thread (like asynchronously). It was implemented some time ago.
Now they get crashes, because some method is called in main thread, while object is destroyed.
Some workaround was created to handle the situation.
Ofcourse, this is just an example of not very good solution, but still the question:
Is there some way to prevent the situation internally in NotVerySafeClass (deny running the methods, if destructor was called already, and force the destructor to wait, until any running method is over (let's assume there is only one method))?
No, no and no. This is a fundamental design issue, and it shows a common misconception in thinking about multithreaded situations and race conditions in general.
There is one thing that can happen equally likely, and this is really showing that you need an ownership concept: The function calling thread could call the function just right after the object has been destroyed, so there is no object anymore and try to call a function on it is UB, and since the object does not exist anymore, it also has no chance to prevent any interaction between the dtor and a member function.
What you need is a sound ownership policy. Why is the code destroying the object when it is still needed?
Without more details about the code, a std::shared_ptr would probably solve this issue. Depending on your specific situation, you may be able to solve it with a more lightweight policy.
Sounds like a horrible design. Can't you use smart pointer to make sure the object is destroyed only when no-one holds any references to it?
If not, I'd use some external synchronization mechanism. Synchronizing the destructor with a method is really awkward.
There is no methods that can be used to prevent this scenario.
In multithread programming, you need to make sure that an object will not be deleted if there are some others thread still accessing it.
If you are dealing with such code, it needs fundamental fix
(Not to promote bad design) but to answer your two questions:
... deny running the methods, if destructor was called already
You can do this with the solution proposed by #snemarch and #Simon (a lock). To handle the situation where one thread is inside the destructor, while another one is waiting for the lock at the beginning of your method, you need to keep track of the state of the object in a thread-safe way in memory shared between threads. E.g. a static atomic int that is set to 0 by the destructor before releasing the lock. The method checks for the int once it acquires the lock and bails if its 0.
... force the destructor to wait, until any running method is over
The solution proposed by #snemarch and #Simon (a lock) will handle this.
No. Just need to design the program propertly so that it is thread safe.
Why not make use of a mutex / semaphore ? At the beginning of any method the mutex is locked, and the destructor wait until the mutex is unlocked. It's a fix, not a solution. Maybe you should change the design of a part of your application.
Simple answer: no.
Somewhat longer answer: you could guard each and every member function and the destructor in your class with a mutex... welcome to deadlock opportunities and performance nightmares.
Gather a mob and beat some design sense into the 'someone' who thought parallel destruction was a good idea :)
Related
Ran across this destructor in a codebase I am debugging.
ManagerImpl::~ManagerImpl() {
// don't go away if some thread is still hitting us
boost::unique_lock<boost::mutex> l(m_mutex);
}
Does it actually serve any useful purpose in a multi-threaded program? It looks like kludge.
I assume the idea is to defer destruction if another thread is calling a function that locks the mutex, but is it even effectively at doing that? ElectricFence segfaults would have me believe otherwise.
It is probably trying to postpone destruction until another thread unlocks the mutex and leaves another member function.
However, this wouldn't prevent another thread calling that function again after the lock in the destructor has been released.
There must be more interaction between threads (which you don't show) to make this code make sense. Still, thought, this doesn't seem to be robust code.
I have a class object whose functions can be called from different threads.
It is possible to get into a situation where Thread1(T1) is calling destructor,
whereas Thread(T2) is executing some other function on the same object.
Let's say T1 is able to call the destructor first, then what happens to the code running in T2?
Will it produce a crash or since the object is already destroyed, the member function will stop running?
Will taking a mutex lock at entry and unlocking at exit of all class functions ensure that there is no crash in any kind of race that will happen between destructor and member functions?
Appreciate your help!
No. Because the logic is flawed. If it is possible at all that T1 is calling the destructor, a mutex will not prevent it from still trying to do that.
There is shared data between T1 and T2 and as such you must make sure that neither will try to call methods on a non-existing shared object.
A mutex alone will not help.
What you'll get is unknown and unpredictable. You're describing a classic multithreading bug / poor design.
An instance should be properly locked before use, and that includes destruction. Once you do that, it's impossible to call a member function on an instance that's being destroyed in another thread.
Locking inside the functions won't help since if 2 separate threads hold references to the same instance and 1 of them causes it to be destroyed, the other thread is holding a bad reference and doesn't know that. A typical solution is to use refcounts, where destruction is at the responsibility of the object itself once no references to it exist. In C++, you'd usually use shared_ptr<> to do this.
To my understanding, if the Singleton::instance() is called in different thread, there might be some problem if both call refer to the first construction of the actual instance.
So if I move the first Singleton::instance() call to the very beginning of the program where no other threads are even created, will this be thread safe now?
Of course, all its member variable are protected by mutex guard when used.
This might open your eyes to a thread-safe Singleton and how easy it isn't.
http://silviuardelean.ro/2012/06/05/few-singleton-approaches/
As per before, it's not very robust if you're requiring it to be created before any threads are kicked off.
Worth noting though, if you compile with C++11, then doing as Brian said (static storage + static method) guarantees thread safety. With any previous versions you will need a mutex, and will run into the caveats mentioned in the link I shared.
So if I move the first Singleton::instance() call to the very beginning of the program where no other threads are even created, will this be thread safe now?
Yes, but this element is not within the Singleton's design and would likely be more robust if it were.
You can often allocate it at file scope or in function scope with static storage within a static method. Verify that your compiler generates exclusion around it or add your own mutex there.
Yes, performing the initial instantiation when you can guarantee there is just one thread extant clearly protects it from other threads causing race conditions.
It doesn't feel terribly robust, though. At the very least, plaster the area with warning comments.
Maybe then you don't need lazy initialization of singleton instance?
If you actually want it then you can protect singleton instance with mutex when you construct it.
Just remember not to put in the header.
If you put the implementation in the header, it may be generated in every compilation unit that uses it. Which means it won't be single.
Also don't compile it in static libraries. This can also lead to multiple instances if the code is linked and merges into several non-static libraries.
If there is no additional thread created yet and you make that move before those threads creation, I don't see a real scenario where you might have problems by using the singleton you already created in any new created multi-threaded environment.
The main thread-safe problem of singleton pattern into a multi-threaded environment is about how to prevent two or more "singleton" instances creation by different threads. I have described this scenario into "Multi-threaded environment" section here.
In my C++ project I have a singleton class. During project execution, sometimes the same singleton class is accessed from two different thread simultaneously. Resulting in two instances of the singleton class is produced, which is a problem.
How to handle such a cases?
Then it's not a singleton :-)
You'll probably need to show us some code but your basic problem will be with the synchronisation areas.
If done right, there is no way that two threads can create two objects of the class. In fact, the class itself should be the place where the singleton nature is being enforced so that erroneous clients cannot corrupt the intent.
The basic structure will be:
lock mutex
if instance doesn't exist:
instance = new object
unlock mutex
Without something like mutex protection (or critical code section or any other manner in which you can guarantee at the language/library level that two threads can't run the code simultaneously), there's a possibility that thread one may be swapped out between the check and the instantiation, leading to two possible instances of your "singleton".
And, as others will no doubt suggest, singletons may well be a bad idea. I'm not quite in the camp where every use is wrong, the usual problem is that people treat them as "god" objects. They can have their uses but there's often a better way, though I won't presume to tell you you need to change that, since I don't know your use case.
If you get two different instances in different threads you are doing something wrong. Threads, unlike processes, share their memory. So memory allocated in one thread (e.g. for an object instance) is also usable in the other.
If your singleton getting two copies its not guarded with mutex. lock a mutex when getting/accessing/setting the internal object.
I believe You are done something like this if(!_instance)_instance = new Singleton() there lies a critical section. which you need to safe guard with a mutex.
Do not use a singleton, It is a well known Anti-Pattern.
A good read:
Singletons: Solving problems you didn’t know you never had since 1995
If you still want to persist and go ahead with it for reasons known only to you, What you need is a thread safe singleton implementation, something like this:
YourClass* YourClass::getInstance()
{
MutexLocker locker(YourClass::m_mutex);
if(!m_instanceFlag)
{
m_instance = new YourClass();
m_instanceFlag = true;
}
return m_instance;
}
Where MutexLocker is a wrapper class for an normally used Mutex, which locks the mutex when creating its instance and unlocks the mutex the function ends.
I would like to create a thread pool. I have a class called ServerThread.cpp, whose constructor should do something like this:
ServerThread::ServerThread()
{
for( int i=0 ; i<init_thr_num ; i++ )
{
//create a pool of threads
//suspend them, they will wake up when requests arrive for them to process
}
}
I was wondering if creating pthreads inside a constructor can cause any undefined behavior that one should avoid running into.
Thanks
You can certainly do that in a constructor but should be aware of a problem that is clearly explained by Scott Meyers ins his Effective/More Effective C++ books.
In short his point is that if any kind of exception is raised within a constructor, then your half-backed object will not be destroyed. This leads to memory leaks. So Meyers' suggestion is to have "light" constructors and then do the "heavy" work in an init method called after the object has been fully created.
This argument is not strictly related to creating a pool of pthreads within a constructor (whereby you might argue that no exception will be raised if you simply create them and then immediately suspend them), but is a general consideration about what to do in a constructor (read: good practices).
Another considerations to be done is that a constructor has no return value. While it is true that (if no exceptions are thrown) you can leave the object is a consistent state even if the thread creation fails, it would be possibly better to manage a return value from a kind of init or start method.
You could also read this thread on S.O. about the topic, and this one.
From a strictly formal point of view, a constructor is really just a
function like any other, and there shouldn't be any problem.
Practically, there could be an issue: the threads may actually start
running before the constructor has finished. If the threads need a
fully constructed ServerThread to operate, then you're in
trouble—this is often the case when ServerThread is a base
class, and the threads need to interact with the derived class. (This
is a very difficult problem to spot, because with the most frequently
used thread scheduling algorithms, the new thread will usually not
start executing immediately.)