-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
bpo-45635: standardize error handling in traceback.c #29905
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
Python/traceback.c
Outdated
if (err != 0) { | ||
return err; | ||
} | ||
if (err == -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.
Nitpick: I prefer the if (err < 0)
C idiom; but it is also what the majority of the code base uses for error handling.
Python/traceback.c
Outdated
done: | ||
return err; |
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.
Did you consider using this "CPython idiom" throughout the PR (ditching err
, where possible)?
if (fn() < 0) {
goto error;
}
return 0;
error:
return -1;
}
IMHO, the advantage is that you've got two clear exit paths; I don't have to backtrack err
to find out if the function will return 0 or -1 for each bad/good path. Probably just personal preference :)
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.
In this case you're right, but there are places where there is some XDECREF that needs to happen regardless of the return value.
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 guess it could be
Py_XDECREF(thing);
return 0;
error:
Py_XDECREF(thing);
return -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.
True, in some situations, it may not be the best alternative because of ref counting; if you need a lot of decrefs before each goto, it is probably not worth it.
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.
Or something like this, if possible.
int ret = fn(obj);
Py_DECREF(obj);
if (ret < 0) {
goto error;
}
return 0;
error:
return -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.
So I did this everywhere and I agree it's much better now.
The only place where things are a little weird is tb_displayline, because there are cases where there is an early exit with return value 0 (depending on the return value of some "should I ignore this error" function).
Python/traceback.c
Outdated
error: | ||
return -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.
We can drop the error
label, and just return -1
iso. goto error
.
Python/traceback.c
Outdated
@@ -545,23 +551,32 @@ display_source_line_with_margin(PyObject *f, PyObject *filename, int lineno, int | |||
*truncation = i - indent; | |||
} | |||
|
|||
if (err == 0) { | |||
err = _Py_WriteIndentedMargin(margin_indent, margin, f); | |||
assert(!err); |
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.
err
is set twice: first at initialisation (set to 0
), and then set to -1
if linjeobj == NULL
in the get-lineno-loop. If lineobj == NULL
, we bail after closing fob
and cleaning up refs. I think it would be an improvement to remove err
and simply return -1
in line 523. Then we'd also get rid of this slightly confusing (to me) assert
:)
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.
Very good!
Co-authored-by: Erlend Egeberg Aasland <[email protected]>
Co-authored-by: Erlend Egeberg Aasland <[email protected]>
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.
Looks good!
OT (but semi-related):
I've only been able to squeeze out ~56% region coverage and ~44% branch coverage of traceback.c
with test_traceback test_warnings test_raise test_pyexpat
. Running the whole test suite gives me ~62% region coverage and ~48% branch coverage, but I've not been able to find out where those last tests are hidden 🔍
IMO, we should...:
- improve region and branch coverage to at least 80%
- consolidate
traceback.c
tests intest_traceback
to make it easier to detect regressions and new bugs
I think I got 85% line coverage on a mac a few days ago (on main). I don't think this branch reduced it by much. |
Wow. |
lcov. Just the standard thing from the devguide. |
👍🏻 But what region/branch coverage did you get? |
It doesn't say, just 85% of the lines and 100% of the functions. |
🤖 New build scheduled with the buildbot fleet by @iritkatriel for commit a05ac63 🤖 If you want to schedule another build, you need to add the ":hammer: test-with-buildbots" label again. |
Those two tests are failing on other branches as well. |
https://bugs.python.org/issue45635