Skip to content

Add PyUnstable_Object_ClearWeakRefsNoCallbacks() function #25

Closed

Description

@colesbury

Background

The use case that types with user defined finalizers (i.e., __del__ methods) need to perform the following sequence if they want to be correct:

  • Clear weakrefs and call callbacks (i.e., PyObject_ClearWeakRefs)
  • Call finalizer (i.e, PyObject_CallFinalizerFromDealloc)
  • Clear weakrefs again, but don't call callbacks (i.e., the proposed PyObject_ClearWeakRefsNoCallbacks)

The third-step is performed internally via _PyWeakref_ClearWeakRefsExceptCallbacks, but that's not a public API. This is performed internally by subtype_dealloc, but extensions cannot always delegate to that function.

Previously, C API extensions used the following pattern, but it's not thread-safe without the GIL and relies on an undocumented private API _PyWeakref_ClearRef:

      PyWeakReference **list = PyObject_GET_WEAKREFS_LISTPTR(self);
      while (*list) {
        _PyWeakref_ClearRef(*list);
      }

Proposed API

// Clears the weakrefs for object `obj`, but does not call their callbacks.
PyAPI_FUNC(void) PyObject_ClearWeakRefsNoCallbacks(PyObject *obj);

Implementation

The implementation already exists as the internal-only _PyWeakref_ClearWeakRefsExceptCallbacks function. Per @vstinner's suggestion, I'd propose that the PyObject_ClearWeakRefsNoCallbacks returns immediately if obj does not support weakrefs.

See also

EDIT: Updated name based on @iritkatriel's suggestion

Activity

  1. gvanrossum commented on May 10, 2024

    @gvanrossum

    No objection from me.

  2. iritkatriel commented on May 10, 2024

    @iritkatriel
    Member

    I don't think the name PyObject_ClearWeakRefsExceptCallbacks is clear. Except in particular.

    Something like PyObject_ClearWeakRefsNoCallbacks maybe.

  3. changed the title [-]Add `PyObject_ClearWeakRefsExceptCallbacks`[/-] [+]Add `PyObject_ClearWeakRefsNoCallbacks`[/+] on May 10, 2024
  4. colesbury commented on May 10, 2024

    @colesbury
    Author

    I've updated the proposed name

  5. vstinner commented on May 12, 2024

    @vstinner

    LGTM.

  6. encukou commented on May 13, 2024

    @encukou
    Collaborator

    While the semantics of PyObject_ClearWeakRefsNoCallbacks function itself are clear, it seems that anyone calling it is quite deep in implementation details.
    I worry that by exposing the function, we're implicitly saying that it's OK to re-implementing subtype_dealloc, or at least the “clear/call del/clear again” dance.

    It seems better to expose this as PyUnstable_Object_ClearWeakRefsNoCallbacks: if you use this function, you better be checking What's News and you better be prepared to adjust code for each new release.
    (Perhaps one of those releases will add a PyObject_Finalize() that abstracts away a well-defined chunk of subtype_dealloc. But even if we add something like that in 3.14, a transitional PyUnstable_Object_ClearWeakRefsNoCallbacks would be nice to have.)

  7. colesbury commented on May 13, 2024

    @colesbury
    Author

    PyUnstable_Object_ClearWeakRefsNoCallbacks is fine with me too.

  8. colesbury commented on May 22, 2024

    @colesbury
    Author

    @vstinner - is PyUnstable_Object_ClearWeakRefsNoCallbacks okay with you?

  9. vstinner commented on May 22, 2024

    @vstinner

    I worry that by exposing the function, we're implicitly saying that it's OK to re-implementing subtype_dealloc, or at least the “clear/call del/clear again” dance.

    IMO it's ok to reimplement something like subtype_dealloc, since 3rd party extensions do it, and that's why Sam wants to make the function public. I'm not sure that the function needs to be tagged as "unstable". The documentation can be clear about where and when it should be used or not.

  10. vstinner commented on May 31, 2024

    @vstinner

    It seems like we are ok with the feature, but not in which API it should be added: how the function should be named. I'm not sure how to resolve this disagreement, so I propose a poll/vote below.

    Function name: please pick only name :-)

    PyUnstable_Object_ClearWeakRefsNoCallbacks() - unstable API, rationale: #25 (comment)

    PyObject_ClearWeakRefsNoCallbacks() - public API, rationale: #25 (comment)

  11. encukou commented on May 31, 2024

    @encukou
    Collaborator

    IMO it's ok to reimplement something like subtype_dealloc, since 3rd party extensions do it[...] The documentation can be clear about where and when it should be used or not.

    I'd need to see that documentation to be convinced.

  12. zooba commented on May 31, 2024

    @zooba

    I lean towards the "unstable" marking, just so we can remove it within a release. I wouldn't expect the API to change in any other meaningful way apart from the function no longer doing what the caller thinks it is doing.

  13. erlend-aasland commented on May 31, 2024

    @erlend-aasland

    I chose PyObject_ClearWeakRefsNoCallbacks, but I won't oppose the unstable variant (though I think it is a weak candidate for the unstable tier).

  14. encukou commented on Jun 6, 2024

    @encukou
    Collaborator

    We discussed this on a meeting, and decided that it should be unstable API. Please go with PyUnstable_Object_ClearWeakRefsNoCallbacks.

  15. changed the title [-]Add `PyObject_ClearWeakRefsNoCallbacks`[/-] [+]Add `PyUnstable_Object_ClearWeakRefsNoCallbacks()` function[/+] on Jun 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions