-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
runtime/exitcodes: Set exit code according to the SystemExit exception. #15730
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
Conversation
Code size report:
|
There are two independent things in this PR:
Both of these things seem reasonable. But for (1) it would be great if this was in a separate commit, to show exactly what's changed for that. And it also needs to have a separate option to control it, eg |
} else { | ||
mp_obj_print(val, PRINT_STR); | ||
mp_print_str(&mp_plat_print, "\n"); | ||
ret = PYEXEC_UNHANDLED_EXCEPTION; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the intention of printing the value here? This is quite unconventional to return a non-int value in a SystemExit
, so maybe this bit can either do nothing, or call mp_obj_print_exception
.
But, see also how the unix port handles this: ports/unix/main.c:handle_uncaught_exception
. Maybe it's worth copying that code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is to keep the behavior consistent with real python:
https://python.readthedocs.io/en/latest/library/exceptions.html#SystemExit
If the value is an integer, it specifies the system exit status (passed to C’s exit() function); if it is None, the exit status is zero; if it has another type (such as a string), the object’s value is printed and the exit status is one.
I know it strictly doesn't have to be and that it is something a little different, but I don't see any reason with not honoring this particular behavior.
Do you want me to change it in some way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the value is an integer,
Makes sense, but minor remark: I don't think it is 100% guaranteed (because of different object representations) that mp_obj_is_small_int(val)
expresses 'is an integer value' exactly, i.e. there might be integers whos value is larger than what a small int can represent but are still a valid exit code? So perhaps this should try to extract an integer value without forcing it to be a small int?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that a valid exit code is only one byte long anyway, 0 to 255 (sometimes -1, which is equivalent to 255). So I don't think this should be an issue. Is there a case where bigger exit codes might be needed? Can you point to some documentation where they are used? What function do you suggest instead of mp_obj_is_small_int(val)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the int is passed to the C exit function.
According to its docs, https://man7.org/linux/man-pages/man3/exit.3.html, only the 0xFF part (the least significant byte, 0-255) is masked and used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is masked and used.
Those are some version of linux-specific docs so in my understanding they only specify one particular use case 'returned to the parent when using wait'. It's easy enough to find conflicting information which shows the full 32bit can in fact be used both on unix and especially on windows where it's not uncommon; first search result: https://stackoverflow.com/questions/179565/exit-codes-bigger-than-255-possible.
What function do you suggest instead
Hmm, good question. Also depends on whether it should be an actual integer (mp_obj_get_int
), or something which can be converted to an integer (mp_obj_get_int_maybe
). But in any case another small issue is that those use mp_int_t
not int
. Probably fine to just cast the result to int
though for completeness I'd document that somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mp_obj_is_small_int
should be fine up to 32bits, right? I understand that this is a "pointer-size int". Is it correct?
re mp_obj_get_int_maybe
- is there a method/helper, which can check whether it is castable? To run the check before the get and maybe do something else with the object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mp_obj_is_small_int should be fine up to 32bits, right? I understand that this is a "pointer-size int". Is it correct?
It's stored in a machine word, but it has 1 or 2 bits less available for the actual representation, see mpconfig.h. So not necessarily 32 bits.
re mp_obj_get_int_maybe - is there a method/helper, which can check whether it is castable? To run the check before the get and maybe do something else with the object.
On second thought mp_obj_get_int_maybe should not be used here because it can fall back to calling MP_UNARY_OP_INT_MAYBE
which is probably not intended, and I doubt anyone is going to use it anyway. So probably:
if (mp_obj_is_int(val)) {
val= (int) mp_obj_int_get_truncated(arg);
}
is ok here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I applied this and force pushed. Should be ok resolved now.
a931243
to
8b5f810
Compare
Thank you for your time and input. I changed it according to your comments. |
0319862
to
1fc878b
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #15730 +/- ##
==========================================
- Coverage 98.43% 98.43% -0.01%
==========================================
Files 161 163 +2
Lines 21281 21294 +13
==========================================
+ Hits 20948 20960 +12
- Misses 333 334 +1 ☔ View full report in Codecov by Sentry. |
933c6cf
to
1ebff3f
Compare
Is it ok now, in its current form? |
What blocks it from mergin? |
@@ -37,6 +37,23 @@ extern pyexec_mode_kind_t pyexec_mode_kind; | |||
|
|||
#define PYEXEC_FORCED_EXIT (0x100) | |||
|
|||
#if MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING | |||
#define PYEXEC_NORMAL_EXIT (0) | |||
#define PYEXEC_UNHANDLED_EXCEPTION (1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does one distinguish between an unhandled exception, and a SystemExit(1)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One doesn't. That is ok. It is not distinguishable in other programs as well. Only by additional stderr output
Signed-off-by: John Smith <jsmith@jsmith.cz>
1ebff3f
to
13cccd3
Compare
Ok, I updated the code according to the comments |
Is there anything else I should update, or is this ok to accept and merge? @dpgeorge |
Superceded by #15863 |
Summary
Add abort setup code (nlr_set_abort) to standard runtime. This makes the standard runtime respond to abort signal without any further modifications.
Third time is a charm, this PR continues previous PRs, originally at #14419 and later #15392
Testing
Tested on ESP32, should work in other places. The changes are guarded by
#if
abort is enabled in the runtime -> only people who want the abort functionality will get this change.Trade-offs and Alternatives
This code may return non-zero exit code in scenarios where previous version did return zero exit code. The exit codes are configurable and the defaults are zero, so not to introduce any breaking changes.