"Robert O'Callahan" roc+@cs.cmu.edu writes:
Of course it has to be 100% reliable, but since you're dealing with failing processes it's not 100% clear what 100% reliability is. Anyway, I think 100% reliability is possible for any plausible definition.
For a mutex the basic definition is obviously that you can never have two threads holding the mutex at the same time, and that when it is released some other thread has a chance at grabbing it. This has to be true no matter what the process does, including corrupting memory or crashing. You also need to make sure nothing a process does should be able to crash/hang the wineserver or another process (except if they fight over the same mutex of course), and then there is the small matter of respecting the Win32 semantics...
Actually it is the last constraint that is the main problem. You can certainly provide some kind of mutexes using shared memory; but we don't need just 'some kind', we need Win32 mutexes. This means a mutex is identified by a handle that can be manipulated by CloseHandle or DuplicateHandle; it means you need to detect and handle abandoned mutexes; it means you must support WaitForMultipleObjects, including the 'all' case where you cannot grab the mutex unless all objects are signaled; all things that I didn't see in your implementation ;-)
Alexandre Julliard wrote:
For a mutex the basic definition is obviously that you can never have two threads holding the mutex at the same time, and that when it is released some other thread has a chance at grabbing it. This has to be true no matter what the process does, including corrupting memory or crashing.
... but not including "process randomly decides to call AcquireMutex again", presumably.
So your concern is simply that if it's too simple to lock the mutex, then you have an unacceptably high probability of a runaway process accidentally locking the mutex, whereas you regard the probability of the process accidentally calling AcquireMutex again (or executing the protected control transfer on its own) as acceptably low. That seems reasonable.
You can vastly reduce the probability of accidental locking by changing the client_locked field to an int and requiring a specific magic number to be stored there to signal a taken lock. You can vary the magic number per mutex, and store it in your auxiliary per-mutex data structures XORed with some known constant, to ensure that the magic number is never stored anywhere in memory except for the lock field.
But if "executes a protected control transfer" is your gold standard of an action that is so unlikely to happen by chance it must be the intended behaviour of the process, then of course no other solution will be acceptable.
You also need to make sure nothing a process does should be able to crash/hang the wineserver or another process (except if they fight over the same mutex of course),
I think we're there.
and then there is the small matter of respecting the Win32 semantics...
Yeah, but that doesn't seem fundamental --- the wineserver can always take ownership of the mutex itself when it needs to do a complex atomic operation. I'll let Gavriel work out the details :-).
Rob