Use Open3.capture3 to avoid deadlock between stdout/stderr in subprocess #959
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
While investigating a possible issue with our internal use of wicked_pdf / wkhtmltopdf, I found this issue in the source.
After opening the wkhtmltopdf subprocess we attempt to read stderr, and we later use that data to determine whether the process failed or not. But because stdout is open and we ignore it, there is a possibility that the process may deadlock. This can happen if wkhtmltopdf fills its stdout buffer before writing to stderr, in which case the kernel will pause the wkhtmltopdf process until someone reads the buffered stdout data. Because it is paused, there can be no new data written to stderr, which blocks ruby and would cause deadlock.
See discussion here re: Open3.popen3 https://docs.ruby-lang.org/en/2.0.0/Open3.html#method-i-popen3
This patch replaces popen3 with capture3, which allows Open3 to manage the process pipes and simply returns the full stdout, stderr, and process exit status after the subprocess completes. I've also added the process status to the error message and added a case to cover the possibility that the process exits with an error code but does not print anything to stderr.
I haven't added any test cases, but I believe that existing test coverage should guarantee that the subprocess call still works as expected.