re: https://github.com/chaincodelabs/libmultiprocess/pull/129#discussion_r1930545346
Clang thread safety is aware of this:
Thanks, this is interesting. I’m a little unsure how clang knows that no mutex is required to access the variable in the destructor. It doesn’t seem like a totally safe assumption to make because I could easily think of cases where locking the mutex in a destructor would be required, and then clang wouldn’t diagnose any problem. But maybe it is just assuming that typical destructors aren’t blocking or doing anything complicated, and the mutex is about to be destroyed anyway, and that is enough proof of ownership.
I assume the thread sanitizer is the same even though I couldn’t demonstrate this easily.
This could also be the case, but I wouldn’t assume it. Thread sanitizer (as far as I know) does not treat destructors differently than other methods, and is operating at a lower level just looking at what mutexes are held during reads and write and what synchronization events are happening between reads and writes.
It’s definitely possible you are right and dropping locks from this code is perfectly ok. So just for the sake of this PR I don’t want to expand it by dropping an already existing lock, but, that could be a good change to make in a followup.
The state in the object is still valid while the destructor method is running, and it should be fine for other threads to access it.
True, but then the problem arises that after the destructor finishes, without further synchronization, the memory that contains the object is freed. So it would be a serious read-after-free bug if another method is being executed while the destructor is being called because it could happen that the destructor finishes and the memory freed while the other method is still executing. Any mutexes within the object locked inside the destructor will be unlocked when the destructor finishes and before the memory is freed, so they cannot be used for synchronization with the other method.
This is all true but it is ok for a destructor to block and wait for other events and other threads. And as long as it is waiting, it is ok for other threads to access the object and call its methods.