Elsewhere I showed an example of where the obvious is not obvious. This example is much more extreme and I am still not sure of the best way to handle it.
In UNIX it is possible to use "System V semaphores" to control access to shared resources. The basis of this is a set of several semaphores; one gets a handle to the set of semaphores and then calls functions to modify the set's state. Unfortunately when one creates a set (as a result of getting a handle to a set that doesn't yet exist) the set is created in an ill-determined state. Therefore one has to initialise the set before it can safely be used. So how does the initialiser make sure no-one else can access the set before it is properly initialised? This is a reasonably well known race condition and is dealt with in one of W Richard Stevens' excellent texts, UNIX Network Programming, 2nd edition Volume 2. I am not going to give the full details here; I encourage anyone who is interested to buy the book. Broadly it goes like this:
The first process manages to create the sempahore set using "semget". Thus it has the task of setting up the semaphores. It initialises all of the semaphores by calling "semctl", initialising one of the semaphores to a value other than the required (e.g. 0 when it should be 1). Then it calls "semop" to change that last value to the correct value.
Any other process will know that it is not the first because it will not be able to create the semaphore set. It must then wait (using wasteful sleep loops) until the first process has finished initialising the set. But how does it know when that is?
Associated with the set of semaphores is a control structure, whose values can be queried. semget is guaranteed to initialise the sem_otime member of that structure to 0 and semop is guaranteed to update that sem_otime member to the current time. Thus the subsequent processes have to query the sem_otime repeatedly until it becomes non-zero. Clearly this is fine except for one small risk; it depends on the fact that semctl does not alter the sem_otime value. The manual page for semctl does not specify this one way or the other and so we have little choice but to hope and add protection such as using the assert macro.
So here we have an example where correct behaviour depends upon absence of undesirable behaviour rather than the converse.