std: Improve pipe functionality

* os::pipe() now returns `IoResult<os::Pipe>`
* os::pipe() is now unsafe because it does not arrange for deallocation of file
  descriptors
* PipeStream::pair() has been added. This is a safe method to get a pair of
  pipes.
* Dealing with pipes in native process bindings have been improved to be more
  robust in the face of failure and intermittent errors. This converts a few
  fail!() situations to Err situations.

cc #13538
Closes #14724
[breaking-change]
This was done out of a desire to not write the windows/unix pipe() implementation in both librustuv and libnative. By having it in libstd, however, it needs to convert the errors a few times (pretty sub-par).

I'm not super happy with this though. The current process-spawning api also deals with file descriptors which is one of the reasons I left the `os::pipe` api in libstd rather than removing it entirely.

Hm, I may need to go back to the drawing board for all of this...