Refactor to use dispatch_io for tasks, and wait for EOF

Hopefully resolves #139 and #135.

/cc @joshaber @keithduncan
I’d say yes as the lifetime of the stream the file descriptors reference is tied to each file handle of the pipe which will `close(2)` their handle on dealloc.

As we pull the file descriptor out for use directly (an interior pointer problem of sorts) I’d rather the IO channel owned the file descriptor and `close(2)` it in the cleanup handler, rather than relying on or keeping the file handles alive.