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

Python object INCREF verification #3023

Merged
merged 4 commits into from
Aug 29, 2024
Merged

Python object INCREF verification #3023

merged 4 commits into from
Aug 29, 2024

Conversation

ferdonline
Copy link
Member

@ferdonline ferdonline commented Jul 31, 2024

Objective

Improve bindings: simplify code and improve reference management.

This PR

  • Verify every occurrence of Py_INCREF. As an idiom, we move it immediately before to the place which utilizes the reference, either an assignment, or a return.
  • Simplify conditional blocks with X[INC/DEC]REF

Originally

Apply an idiom to reduce mental load and eventually fix some ref count issues:
On pyobjA_ptr = pyObjB_ptr one should always INCREF(pyObjB_ptr) and XDECREF(pyobjA_ptr), except when pyObjB_ptr is already a new reference

However, Py_INCREF is currently almost exclusively used for an object being assigned to a PyObject* field of a newly created object. Such fields come non-initialized, possibly non-0, and therefore we can't rely on XDECREF.

@bbpbuildbot

This comment has been minimized.

Copy link
Collaborator

@1uc 1uc 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 overall. Please any additional changes that are not strictly related to what has been started here to a different PR.

There's a couple of things I don't understand and I'm hoping you could clarify.

src/nrnpython/nrnpy_nrn.cpp Show resolved Hide resolved
src/nrnpython/nrnpy_nrn.cpp Outdated Show resolved Hide resolved
src/nrnpython/nrnpy_nrn.cpp Show resolved Hide resolved
src/nrnpython/nrnpy_nrn.cpp Outdated Show resolved Hide resolved
src/nrnpython/nrnpy_nrn.cpp Outdated Show resolved Hide resolved
src/nrnpython/nrnpy_nrn.cpp Outdated Show resolved Hide resolved
@ferdonline ferdonline changed the title Python object Reference verificartion. Use INCREF/XDECREF idiom on assign Python object Reference verification. Use INCREF/XDECREF idiom on assign Jul 31, 2024
@ferdonline
Copy link
Member Author

I extracted some of these changes to #3024 so that here we can focus on the INCREF/DECREF verification

@1uc 1uc mentioned this pull request Jul 31, 2024
@bbpbuildbot

This comment has been minimized.

@ferdonline ferdonline changed the base branch from master to enh/py_bind/nb_api_more July 31, 2024 17:30
@bbpbuildbot

This comment has been minimized.

Copy link

✔️ a0d0d07 -> Azure artifacts URL

@bbpbuildbot

This comment has been minimized.

@ferdonline ferdonline changed the title Python object Reference verification. Use INCREF/XDECREF idiom on assign Python object INCREF verification Aug 1, 2024
@ferdonline ferdonline marked this pull request as ready for review August 1, 2024 21:49
Copy link
Collaborator

@1uc 1uc left a comment

Choose a reason for hiding this comment

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

Seems fine, only minor comments. Please review the part that's a bug/leak fix. If the change is correct, please isolate it in a separate PR. The reason is that this PR mostly doesn't matter. However, hidden in the middle is a bug fix, if we keep it here it's less obvious that the change was intentional; and the commit title wont alert us to the fact that this commit also fixes a leak.

src/nrnpython/nrnpy_nrn.cpp Show resolved Hide resolved
src/nrnpython/nrnpy_nrn.cpp Show resolved Hide resolved
src/nrnpython/nrnpy_nrn.cpp Show resolved Hide resolved
src/nrnpython/nrnpy_nrn.cpp Outdated Show resolved Hide resolved
Base automatically changed from enh/py_bind/nb_api_more to master August 7, 2024 09:41
Copy link

✔️ 9775324 -> Azure artifacts URL

@bbpbuildbot

This comment has been minimized.

Copy link

✔️ aa969ae -> Azure artifacts URL

@bbpbuildbot

This comment has been minimized.

Copy link
Collaborator

@1uc 1uc left a comment

Choose a reason for hiding this comment

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

The leak fix needs to extracted.

Copy link

sonarcloud bot commented Aug 29, 2024

Copy link

codecov bot commented Aug 29, 2024

Codecov Report

Attention: Patch coverage is 93.54839% with 2 lines in your changes missing coverage. Please review.

Project coverage is 67.26%. Comparing base (2996006) to head (0299c65).
Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/nrnpython/nrnpy_nrn.cpp 93.54% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3023      +/-   ##
==========================================
- Coverage   67.27%   67.26%   -0.01%     
==========================================
  Files         571      571              
  Lines      104877   104874       -3     
==========================================
- Hits        70554    70543      -11     
- Misses      34323    34331       +8     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

✔️ 0299c65 -> Azure artifacts URL

@1uc 1uc merged commit 7d518dd into master Aug 29, 2024
38 checks passed
@1uc 1uc deleted the enh/py_bind/ref_control branch August 29, 2024 11:31
1uc pushed a commit that referenced this pull request Sep 19, 2024
### Context

Following #3023, we noticed that there might be extraneous call to INCREF, given it's done on an object returned by `tp_alloc`, which should return a new reference. New references have their ref count to 1 and therefore it should not require any additional reference increment.

### Bug Reproducer

~$ nrniv -python
```python
from neuron import h
h("create soma")
h("objref nc, nil")
h('soma nc = new NetCon(&v(0.5), nil)')
seg = h.nc.preseg()
```
Exit the interpreter and observe
```
Fatal Python error: bool_dealloc: deallocating True or False: bug likely caused by a refcount error in a C extension
```

### Scope

 - Replace the code by the single function `newpysechelp(sec)` which seems to do just the right thing.
 - Added unit test

### Testing

Two python unit tests added:
 - test_seg_from_sec_x_ref_python
 - test_seg_from_sec_x_ref_hocpy

For debug-ability it might be worth to add the following snippet to `seg_from_sec_x`
```
auto* psec = sec->prop->dparam[PROP_PY_INDEX].get<void*>();
fprintf(stderr, "In seg_from_sec_x. Pysec=%p\n", psec);
```

We will see along the lines of
```
In seg_from_sec_x. Pysec=0x7fa081736150
In seg_from_sec_x. Pysec=0x0
```
ensuring the we are exercising both cases.

After dropping the original section, the pure-python code end up with the same number of references as the hoc-python code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants