title: Proper disposal of a Grand Central Dispatch I/O channel
body: <p>I'm confused about how to correctly dispose of a Grand Central Dispatch I/O channel once I'm finished with it. The following (simplified) example causes a crash on some private dispatch queue with the message: <code>BUG IN CLIENT OF LIBDISPATCH: Over-resume of an object</code>:</p>
  
  <pre><code>- (void)beginReading {
      dispatch_io_t channel;
      channel = dispatch_io_create_with_path(DISPATCH_IO_RANDOM, 
                                             "/Path/To/Some/File", 
                                             O_RDONLY, 
                                             0 /*mode*/,
                                             someQueue,
                                             ^(int errorCode) {
                                                 // Cleanup handler; executed once channel is closed. 
                                                 // (Or fails to open.)
                                             });
      // Schedule the read operation
      dispatch_io_read(channel, 0, SIZE_MAX, someQueue, ^(bool done, dispatch_data_t data, int errorCode) {
          NSError *error = (errorCode!=0) ? [NSError errorWithDomain:NSPOSIXErrorDomain code:errorCode userInfo:nil] : nil;
          [self didReadChunk:data isEOF:done error:error];
      });
  
      // No more read operations to come, so we can safely close the channel.
      // (Or can we?)
      dispatch_io_close(channel, 0); 
  
      // We don't need a reference to the channel anymore
      dispatch_release(channel); 
  }
  </code></pre>
  
  <p>I'm guessing that <code>dispatch_io_close()</code> schedules some asynchronous operation to close the channel, and until this operation has finished executing, you mustn't call <code>dispatch_release()</code>on the channel or bad things will happen. But this would be quite surprising: other GCD asynchronous functions, such as <code>dispatch_async()</code>, don't have this restriction. Further, the <code>dispatch_io_close()</code> call doesn't seem to be strictly necessary, as libdispatch appears to close the file with the last call to <code>dispatch_release()</code> on the channel.</p>
  
  <p>It seems to follow from this that if you call <code>dispatch_io_close</code>, you must take care that not to release the channel until its cleanup handler has run. This so irritating that I wonder if it's a bug. Or perhaps I'm missing something?</p>