The suggestion to avoid weak links does not solve the race problem.
T1 operator new, create object, references: 1 T1 passes interface object reference to T2, thinking it can "share" ownership T1 suspends T2 resumes T2 QueryInterface T2 suspends before InterlockedIncrement, references: 1 T1 resumes T1 Calls Release T1 suspends between InterlockedDecrement and operator delete, references: 0 T2 resumes, InterlockedIncrement occurs, references 1 T2 suspends T1 resumes, operator delete executes, references 1 !!! T1 suspends T2 resumes T2 Any reference to the interface is now invalid since it has been deleted with reference count 1.
This is resolvable on the COM server. The COM client, however, should not depend on the server preventing this race condition. Therefore, COM clients MUST NOT pass interface objects between threads. The only thread that must be allowed to access the interface object is the ONE thread, which currently owns the interface object.
T1 should not call Release. Yes, it could call AddRef before passing the interface object to T2. But this may not solve the race, but only move it somewhere else. Best practice is to always support the concept of a single interface object, one owner.
If the COM server wants to support the concept that two (or more) interfaces can refer to some general state of the internal server, the COM server should advertise the contract by supplying the CreateCopyOfInstance method and managing the conflict internally. There are, of course, examples of servers that handle such a "splitter". Take a look at Microsoft's persistent storage interfaces. There the interfaces are NOT "bloated". Each interface must belong to one user (thread / process / independently), and the βfanβ is controlled inside the server by the server using the methods provided by COM clients to control some aspects of conflicting issues. Therefore, Microsoft COM servers must therefore decide race conditions within their contracts to their customers.
source share