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]
Also, this function seems quite unsafe, and very much a low-level building block for `io`, not really an `os` thing. (I.e. would it be better to be in `std::io::pipe` with the rest of the pipe stuff) *shrug*