Skip to content

LRC bug #52

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

Open
TobiasWrigstad opened this issue Mar 14, 2025 · 5 comments
Open

LRC bug #52

TobiasWrigstad opened this issue Mar 14, 2025 · 5 comments
Assignees

Comments

@TobiasWrigstad
Copy link
Collaborator

TobiasWrigstad commented Mar 14, 2025

The following code gets a crazy high LRC:

class Obj: pass

r = Region()
r # Region(lrc=1, osc=0, name=None, is_open=no) --- as expected

r.f = Obj()
r # Region(lrc=6, osc=0, name=None, is_open=yes)

I cannot fathom why lrc=6.

But things get weirder!

r.f = Obj()
r # Region(lrc=5, osc=0, name=None, is_open=yes) --- why LRC==5???
r.f = Obj()
r.f = Obj()
r.f = Obj()
r.f = Obj()
r.f = Obj()
r.f = Obj()
r # Region(lrc=-1, osc=0, name=None, is_open=yes) --- why LRF==-1???

(On phase3 branch.)

@TobiasWrigstad
Copy link
Collaborator Author

Also weird:
Image

@TobiasWrigstad
Copy link
Collaborator Author

OK the above seems explainable:

r = Region()
r.try_close()

returns True but

r = Region()
r
r.try_close()

returns False because _ == r. Also:

r = Region()
r
42 # so that _ == 42
r.try_close()

returns True.

@xFrednet
Copy link
Collaborator

xFrednet commented Mar 15, 2025

I'll investigate this next week, but I have a theory where the two effects could come from:

  1. The high LRC count might come from objects pulled into the region from the Obj() class. Mainly the prototype, and meta type which should have a relatively high RCs leading to a high LRC. You could check for this by creating a second region, moving an Obj() into that one and taking notes of which objects can't be shared.

  2. The negative LRC is potentially an effect of the missing write barrier on objects. When the Obj prototype is inside the region and a new Obj() is created it should increase the LRC. The write barrier will then decrease the LRC when the Obj() is slurped into the region. My guess is that only the decrease happens, you can that this with this code:

    class Obj: pass
    
    r = Region()
    r.f = Obj()
    
    # Take note of LRC
    str(r)
    
    # Create a new local object, which should increase the LRC
    o = Obj()
    
    # Check if the LRC actually increased?
    str(r)

Guess was correct, the object init function only sets the type without a write barrier:

static inline void
_PyObject_Init(PyObject *op, PyTypeObject *typeobj)
{
assert(op != NULL);
Py_SET_TYPE(op, typeobj);
if (_PyType_HasFeature(typeobj, Py_TPFLAGS_HEAPTYPE)) {
Py_INCREF(typeobj);
}
_Py_NewReference(op);
}

@xFrednet
Copy link
Collaborator

The high LRC at the beginning doesn't seem to be a bug but a result of the unicode type being pulled into the region:

Image

@xFrednet
Copy link
Collaborator

xFrednet commented Apr 3, 2025

OK the above seems explainable:

r = Region()
r.try_close()

returns True but

r = Region()
r
r.try_close()

returns False because _ == r. Also:

r = Region()
r
42 # so that _ == 42
r.try_close()

returns True.

Correct, there is still a bug that the binding of the region to the _ didn't increase the LRC.

The relevant code snippet is here:

cpython/Python/sysmodule.c

Lines 750 to 751 in 78cedf2

if (PyObject_SetAttr(builtins, &_Py_ID(_), o) != 0)
return NULL;

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

No branches or pull requests

2 participants