Skip to content

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

Merged
merged 6 commits into from
Dec 7, 2021

Conversation

iritkatriel
Copy link
Member

@iritkatriel iritkatriel commented Dec 3, 2021

if (err != 0) {
return err;
}
if (err == -1)
Copy link
Contributor

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.

Comment on lines 400 to 401
done:
return err;
Copy link
Contributor

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 :)

Copy link
Member Author

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.

Copy link
Member Author

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;
}

Copy link
Contributor

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.

Copy link
Contributor

@erlend-aasland erlend-aasland Dec 3, 2021

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;

Copy link
Member Author

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).

Comment on lines 417 to 418
error:
return -1;
Copy link
Contributor

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.

@@ -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);
Copy link
Contributor

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 :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good!

iritkatriel and others added 3 commits December 7, 2021 10:10
Co-authored-by: Erlend Egeberg Aasland <[email protected]>
Co-authored-by: Erlend Egeberg Aasland <[email protected]>
Copy link
Contributor

@erlend-aasland erlend-aasland left a 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 in test_traceback to make it easier to detect regressions and new bugs

@iritkatriel
Copy link
Member Author

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 in test_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.

@erlend-aasland
Copy link
Contributor

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. gcov or llvm-cov?

@iritkatriel
Copy link
Member Author

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. gcov or llvm-cov?

lcov. Just the standard thing from the devguide.

@erlend-aasland
Copy link
Contributor

lcov. Just the standard thing from the devguide.

👍🏻 But what region/branch coverage did you get?

@iritkatriel
Copy link
Member Author

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.

@iritkatriel iritkatriel added the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Dec 7, 2021
@bedevere-bot
Copy link

🤖 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.

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Dec 7, 2021
@iritkatriel
Copy link
Member Author

Those two tests are failing on other branches as well.

@iritkatriel iritkatriel merged commit d596acb into python:main Dec 7, 2021
@iritkatriel iritkatriel deleted the bpo-45635-traceback branch December 8, 2021 20:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants