rework cmd app errors, permit non-zero exit code and custom output #1337
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.
This changes how the command line apps handle errors to ensure we have non-zero exit codes to the OS/shell while also maintaining our own output format. This is important for scripting among other things.
The problem with cobra is that if we return an error from say
RunE
, cobra will insist on prefixing the error message with a text likeError:
which is no good for reasons. We can sorta set this prefix, but it's a somewhat flawed implementation whereby we always end up with at least two spaces prefixing the output we want. This is why we have had theshared/display.PrintErr
always eating the error, I believe.We get around this issue by continuing to swallow the error, but storing the error in the command's context, and then in
main()
pulling it out and setting the exit code if it is not nil. (we don't actually need theerror
, just a bool, but I include the whole thing for debugging).Finally, this PR also resolves related issues with startup and shutdown:
buildServer
function was receiving the background context (my bad) so we couldn't really cancel things like a peer dial that would have to timeout insteadP2Pservice
initializer used a background context(*P2PService).Start
always returned nil even if the context was cancelled and a peer connect returned a non-nil error. This was logically done to allow the loop tocontinue
to other peers, but if the context was cancelled, we need to abort startup. Before this fix, it would go on to initialize other systems, eventually hitting one that cared about the context cancellation.