-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
os: add ProcessState.ExitCode #26539
Comments
If there were no one working on this, I can help add it.:) |
Change https://golang.org/cl/125443 mentions this issue: |
@wgliang - The proposal is still in a discussion phase, and not yet accepted. Once it is accepted, you are most welcome to work on it. But I see you have already sent a CL. :) |
SGTM. I have vague memories of discussion of this earlier and recall that Plan 9 not having integer exit codes being part of the reason we don't have this. But if Windows & Unix both have them, I see no reason not to add it. But if there are Plan 9 related objections, perhaps that could be addressed in naming the method something else, possibly more specific. But current name is fine. Your CL would need docs. |
Kind of unfortunate that os.Exit takes 'code int' while syscall.WaitStatus's method is ExitStatus (not ExitCode). I usually think of the "status" as the code with extra random bits I don't want mixed in (like the C int that is the argument of all the macros in the wait(2) man page). Also StatusCode in HTTP is the int while Status is the string. But given that os.Exit exists and takes an int, I see no portability reason to refuse to return that int in a portable way. (Not worried about Plan 9 here.) Let's call it ProcessState.ExitCode (not ExitStatus) and return -1 (not undefined behavior) if Exited() == false. |
I've updated the PR, PTAL.:) |
Perhaps ExitCode() should return an error to advise that the process doesn't have an exit code? Eg:
This feels like one of those situations where an inline error is likely to result in a surprising unchecked outcome. Especially since a terminated process doesn't necessary have an exit code (Eg, exit via signal). Signals are very system specific, so I don't think there is any need for a similar ExitSignal() method. That probably should be unpacked the usual way. |
@mpx I would much prefer it be clearly documented to return -1 in these cases per @rsc . Like with calling I don't think it will result in a surprising error, since zero is the only "success" status, so folks will be doing things like As for signals, I don't know enough about them to comment. Python does them as |
Experience with I would not be at all surprised if we end up with users confused by unexpected If we had some sort of run-time reporting for failed assertions without panicking (a proposal I intend to make soon), we could report the error and return -1. So my preference would be to formally define |
@benhoyt Even if the code guarantees I don't think using
vs
In general, using
If we want to reduce boilerplate further, I tend to use a helper function like:
Using a helper function like |
I was thinking the normal use case would like more like this:
Or maybe even:
In either case you'd have some fallback for "unexpected error" which would include the -1. Or if you wanted to check for -1 specially, you'd be welcome to. |
Using the
If converting exit codes to error messages is a common pattern, it's easy enough to abstract via a helper function/map which would be simpler again. I'm not convinced an API returning |
At least they'll see -1 and know they did something wrong, as opposed to returning 0 in that case. Let's just proceed with the simple signature approved during the proposal review. |
The caller might not have done anything wrong - the process might have terminated via a signal. They also wouldn't know what went wrong without the boilerplate that this API attempts to avoid. A helper function (like
It would be trivial to wrap the more general function for anyone who wants to hide all failures behind an inline error. I suspect most developers wouldn't want to do that. I understand that everyone has their preferences, so just for your consideration. In either case, making the exit code easier to obtain is a step forward. |
Agreed. To be clear, I'm not suggesting that we change the signature or the behavior from what was approved: only that we tell users “don't call |
For anyone who finds this in a search like I did, this capability was implemented as the following in Go 1.12: https://golang.org/pkg/os/#ProcessState.ExitCode . As described in the first comment, this removes the need to cast the error twice, and the dependency on |
After a bit of discussion on this golang-nuts thread, I propose that we add an
ExitStatus() int
method toos.ProcessState
so that it's significantly simpler to get the exit status of a finished process, and doesn't require the syscall package.Motivation (some of this copied from the thread): I struggled to get the exit status integer of a command executed with os/exec. I followed the documentation through ExitError and ProcessState, but could only find the ProcessState.Success() boolean. After searching Google+StackOverflow I found you can get it, but it requires importing syscall and converting to a syscall type -- pretty klunky.
Here's roughly the code snippet that I'm currently using:
Which is problematic because of all the boilerplate, but also because syscall is platform-specific, and fetching an exit code works on all major platforms (Unix/Linux/macOS/Windows). Even on Plan 9 ExitStatus() is implemented (though admittedly it's a bit of a hack as it just checks to see whether an error message was returned). So this would work for all major systems, and on Plan 9 would just act like the above syscall function that already exists, returning 0 on success or 1 on error.
os.ProcessState
already has aSuccess() bool
method, so this proposal would addExitStatus() int
alongside that. It would return the exit status integer (and possibly be documented to return -1 if the process hasn't finished). This would enable the above code to be something like this:Or actually just this:
There are various reasons for needing the exit code value:
system()
function when implementing a scripting language (my particular case)This exists in other languages, for example Python's subprocess has "returncode" and Java's exec has exitValue().
For what it's worth, @ianlancetaylor said (on the linked golang-nuts thread) that this "seems reasonable to me".
The text was updated successfully, but these errors were encountered: