fix: reading output from orphan process (#7402)
### Description
This PR fixes an unintended behavior where an orphaned process could
result in `turbo` not exiting.
Hitting this behavior required a few things:
- the user defined task spawns it's own child process that inherits
stdout/stderr e.g. `sh -c "sleep 10"` will start a child process `sleep
10`
- an external program kills the parent in a way that doesn't allow it to
clean up children e.g. `SIGKILL`
Use of `child.wait_with_piped_outputs` would then hang until the
orphaned process exits as `stdout`/`stderr` are kept open by the orphan.
We work around this by additionally checking if the child has exited and
if it wasn't a successful exit we abort the reading of stdout/stderr.
We will still read stdout/stderr to completion if the parent process
exits with 0 as it might intentional to have the orphan produce
additional output before it finishes.
This fix only is needed for non-PTY tasks as we close up the control
side of the PTY on child exit which will close the child output.
(I also discovered that we were returning `None` on any `child.wait()`
calls after the first one completed instead of the actual exit value.
The seconds commit fixes this)
### Testing Instructions
Added red->green unit test that produces an orphaned process that keeps
stdout/stderr open.
Closes TURBO-2383