I believe I have done everything correctly. I create a pipe, pass the sink to a writer thread, register the source on my selector with OP_READ, start my selector. Everything
Ok, so I found the problem. First thanks for everyone trying to help. Hopefully you will learn from my mistake. The chain of events were:
1 - I was not draining the receiving buffer (the one the source channel reads into) and it eventually got full.
2 - Now that it is full, pipeSourceChannel.read(readBuffer) returns 0 bytes. There is data to be read but It can't read on a full buffer.
3 - That caused the channel to be closed (i was doing that myself on bytesRead == 0) and the BrokenPipe.
One lesson I learned here: PIPES are tricky. I would think that non-blocking concurrent queues are much simpler to use like this guy here once mentioned: Java NIO Pipe vs BlockingQueue