Skip to content
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

gh-99537: Use Py_SETREF() and Py_CLEAR() functions in C code #99538

Closed
wants to merge 2 commits into from
Closed

gh-99537: Use Py_SETREF() and Py_CLEAR() functions in C code #99538

wants to merge 2 commits into from

Conversation

vstinner
Copy link
Member

@vstinner vstinner commented Nov 16, 2022

Replace "Py_XDECREF(var); var=NULL;" with "Py_CLEAR(var);". Do the
same when Py_DECREF() is used for similar code.
Fix race condition in usage code patterns:

* Replace "Py_DECREF(var); var = new;" with "Py_SETREF(var, new);"
* Replace "Py_XDECREF(var); var = new;" with "Py_XSETREF(var, new);"
* Replace "Py_CLEAR(var); var = new;" with "Py_XSETREF(var, new);"

Other changes:

* Replace "old = var; var = new; Py_DECREF(var)"
  with "Py_SETREF(var, new);"
* Replace "old = var; var = new; Py_XDECREF(var)"
  with "Py_XSETREF(var, new);"
* And remove the "old" variable.
@vstinner
Copy link
Member Author

I splitted my PR in two commits:

  • Py_CLEAR
  • Py_SETREF

To ease review. Maybe it can be two PRs.

@erlend-aasland
Copy link
Contributor

The Py_XSETREF/Py_SETREF change looks very good; increased readability, which also brings increased maintainability. I'm not quite sure about the Py_CLEAR change. It introduces Py_XDECREF in places where Py_DECREF was previously used1.

Footnotes

  1. Thinking about it, perhaps there should've been a Py_XCLEAR and a Py_CLEAR... but there's not.

@vstinner
Copy link
Member Author

I'm not quite sure about the Py_CLEAR change. It introduces Py_XDECREF in places where Py_DECREF was previously used

I thought that performance of an if(NULL) was not important, but I can revert this part.

@erlend-aasland
Copy link
Contributor

I thought that performance of an if(NULL) was not important, but I can revert this part.

If you benchmark it, I'm sure the performance hit is lost in noise :)

@@ -624,8 +624,7 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self,

switch (PyObject_IsTrue(result)) {
case -1:
Py_DECREF(result);
result = NULL;
Py_CLEAR(result);
Copy link
Member

Choose a reason for hiding this comment

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

Py_DECREF(var); var=NULL only has a race condition if var is accessible from outside the function, right? I don't think there is any race condition if var is just a local variable.

Copy link
Contributor

@erlend-aasland erlend-aasland Nov 17, 2022

Choose a reason for hiding this comment

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

Yeah, for those cases you only get increased readability and fewer lines of code.

Copy link
Member Author

Choose a reason for hiding this comment

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

You're right, the code is only unsafe if the variable is shared between two function calls. It can be a static variable inside the function, a global variable, an object attribute, etc. Here result is a local variable, so the code is safe. Do you think that the commit message should be enhanced?

@erlend-aasland is right, it's also about about increasing readability.

@vstinner
Copy link
Member Author

I splitted this PR into 3 PRs, but just for Py_SETREF():

I replaced "Fix race condition" with "Fix potential race condition".

@vstinner vstinner closed this Nov 21, 2022
@vstinner vstinner deleted the py_setref branch November 21, 2022 17:27
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