Most of my work nowadays is writing Haskell, but to interop with other systems we have COM server which fires off the Haskell processes and communicates with them through pipes - we could do things less indirectly, but this is a nice, simple way of decoupling the components. However, the pipes have been really quite irritating to deal with.
First off, Win32 anonymous pipes (the kind of pipes you'd expect to use to communicate with a child process) don't support WaitForMultipleObjects. This is really quite irritating if you want to support select-style reading from your sub-process. Why might you want to do this? Well, the alternatives are:
So, instead I tried WaitForMultipleObjects-ing on the handle. MSDN said I couldn't, but MSDN lies about lots of stuff. It turns out MSDN was telling the truth, although it wasn't immediately obvious. It basically immediately returns (without error), so we then perform a blocking read on the pipe, leading to the deadlock described above, as we wait to read one pipe, and the child waits to write the other.
The solution? Use named pipes, with unique names. This link contains the basic source, which you may want to adjust for your personal use, while complaining that the Win32 API really should do this right itself, especially since it's such a common usage case.