title: Correctly destroying named System V semaphores
body: <p>I'm using named System V semaphores to lock a file across all my apps on OSX and linux. Not prettiest of APIs by any definition.</p>
  
  <p>It seems to work, but I can't quite figure out how to properly destroy the semaphore after everybody is done with it.</p>
  
  <p>General logic is like this:</p>
  
  <p><strong>Creating:</strong></p>
  
  <p>[1] Thread or process tries to open a semaphore set with key_t created for the file by ftok(). Set contains 2 semaphores. [2] If semaphore set doesn't exist, it is created with 666 permissions. [3] "Lock" (one of the semaphores) set into released state (value 1). [4] "Reference count" (another semaphore in the same set) is incremented.</p>
  
  <p><strong>Locking/unlocking:</strong></p>
  
  <p>To lock [5], a thread decrements the value of "Lock" semaphore by 1 (with undo), thus waiting if it is already zero. To unlock [6], thread increments it by one, thus allowing somebody else to lock it.</p>
  
  <p><strong>Destroying:</strong></p>
  
  <p>[7] "Reference count" semaphore is attempted to be decremented (with IPC_NOWAIT flag). [8] Its value is checked to be 0, and if it is [9] semaphore set is destroyed.</p>
  
  <p>(There is also a layer of logic based on thread local storage to make the lock recursive within one thread.)</p>
  
  <p>The questions are: </p>
  
  <ul>
  <li>How do I synchronize steps [1] and [2]? (if semaphore set doesn't exist, but while we were counting stars, it was created by somebody else so now creation will fail too)</li>
  <li>How do I synchronize steps [4] with [8] so that [9] does not kill me prematurely?</li>
  <li>Are there any other race conditions?</li>
  </ul>
  
  <p>PS: While POSIX semaphores have much nicer API, I don't think I can survive sem_inlink() behavior as described here:</p>
  
  <blockquote>
    <p>Calls to sem_open() to re-create or
    re-connect to the semaphore refer to a
    new semaphore after sem_unlink() is
    called.</p>
  </blockquote>
  
  <p>So I will have no way to release them...</p>