Skip to content

Add an id field to PyInterpreterState. #73288

Closed

Description

@ericsnowcurrently
BPO 29102
Nosy @brettcannon, @ncoghlan, @vstinner, @ericsnowcurrently, @serhiy-storchaka, @zooba
PRs
  • bpo-29102: Add a unique ID to PyInterpreterState. #1639
  • Files
  • interpreter-id.diff
  • interpreter-id-2.diff
  • interpreter-id-3.diff
  • interpreter-id-4.diff
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/ericsnowcurrently'
    closed_at = <Date 2017-05-25.00:22:01.977>
    created_at = <Date 2016-12-29.06:53:42.384>
    labels = ['interpreter-core', 'type-feature', '3.7']
    title = 'Add an id field to PyInterpreterState.'
    updated_at = <Date 2017-05-25.00:22:01.976>
    user = 'https://github.com/ericsnowcurrently'

    bugs.python.org fields:

    activity = <Date 2017-05-25.00:22:01.976>
    actor = 'eric.snow'
    assignee = 'eric.snow'
    closed = True
    closed_date = <Date 2017-05-25.00:22:01.977>
    closer = 'eric.snow'
    components = ['Interpreter Core']
    creation = <Date 2016-12-29.06:53:42.384>
    creator = 'eric.snow'
    dependencies = []
    files = ['46070', '46094', '46100', '46105']
    hgrepos = []
    issue_num = 29102
    keywords = ['patch']
    message_count = 32.0
    messages = ['284229', '284230', '284232', '284233', '284273', '284276', '284278', '284280', '284283', '284290', '284328', '284329', '284332', '284335', '284350', '284353', '284359', '284366', '284374', '284378', '284380', '284395', '284406', '293899', '294116', '294212', '294232', '294312', '294315', '294370', '294371', '294417']
    nosy_count = 7.0
    nosy_names = ['brett.cannon', 'ncoghlan', 'vstinner', 'grahamd', 'eric.snow', 'serhiy.storchaka', 'steve.dower']
    pr_nums = ['1639']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue29102'
    versions = ['Python 3.7']

    Activity

    1. ericsnowcurrently commented on Dec 29, 2016

      @ericsnowcurrently
      MemberAuthor

      Currently there isn't any way to uniquely identify an interpreter. This patch adds a new "id" field to the PyInterpreterState struct. The ID for every new interpreter is set to the value of an increasing global counter. That means that the ID is unique within the process.

      IIRC, the availability of unique ID would help tools that make use of subinterpreters, like mod_wsgi. It is also necessary for any effort to expose interpreters in Python-level code (which is the subject of other ongoing work).

      The patch also adds:

      unsigned long PyInterpreterState_GetID(PyInterpreterState *interp)

      Note that, without a Python-level interpreters module, testing this change is limited to extending the existing test code in test_capi.

    2. serhiy-storchaka commented on Dec 29, 2016

      @serhiy-storchaka
      Member

      Why not use just the pointer to PyInterpreterState itself?

    3. ericsnowcurrently commented on Dec 29, 2016

      @ericsnowcurrently
      MemberAuthor

      Pointers can get re-used, so they aren't temporally unique.

    4. serhiy-storchaka commented on Dec 29, 2016

      @serhiy-storchaka
      Member

      What is the use case of keeping the uniqueness after deleting an interpreter?

    5. zooba commented on Dec 29, 2016

      @zooba
      Member

      Tracking purposes mainly, so someone outside the interpreter state can tell when it's no longer there. Making interpreter states weak-referencable would have a similar effect, and could very well use this id if we didn't need the callback.

    6. serhiy-storchaka commented on Dec 29, 2016

      @serhiy-storchaka
      Member

      If add an API for getting an unique ID of the interpreter state, is it needed to add an API for getting the interpreter state by ID?

    7. ericsnowcurrently commented on Dec 29, 2016

      @ericsnowcurrently
      MemberAuthor

      Three reasons come to mind:

      1. threads are identified by small integers
      2. long, random-looking IDs are not human-friendly, and subinterpreter IDs will be used like thread IDs are
      3. related to what Steve said, temporally unique IDs allow us to be confident about whether or not an interpreter has been destroyed (and how many interpreters there have been)

      Since PyInterpreterState is not a PyObject, using weakrefs to address the third point won't work, right?

    8. serhiy-storchaka commented on Dec 29, 2016

      @serhiy-storchaka
      Member

      There is an issue with integer identifiers of threads. See bpo-25658 and https://mail.python.org/pipermail/python-ideas/2016-December/043983.html.

    9. zooba commented on Dec 29, 2016

      @zooba
      Member

      That's an issue with TLS initialisation, not thread IDs. It's easily solved by defining an "uninitialized" value (e.g. 0) and an "invalid" value (e.g. -1).

      Interpreter states are in a linked list, so you can traverse the list to find one by ID.

      WRT weakrefs, we can't use them directly, but I suspect the higher-level API will need it. Possibly adding a callback on finalisation would fill both needs, but I like having a reliable ID - otherwise we'll probably end up with multiple different IDs managed indirectly via callbacks. (Perhaps a single callback for when any interpreter is finalized that passes the ID through? That should work well, since the ID is designed to outlive the interpreter itself, so it can be an asynchronous notification.)

    10. ericsnowcurrently commented on Dec 29, 2016

      @ericsnowcurrently
      MemberAuthor

      Interpreter states are in a linked list, so you

      can traverse the list to find one by ID.

      Exactly. At first I had added a PyInterpreterState_FindByID() or something
      like that. However, as you noted, I realized it wasn't necessary. :)

      WRT weakrefs, we can't use them directly, but I suspect the higher-level
      API will need it...

      Everything you said about weakrefs sounds good. We can discuss more when
      we get to that high-level API.

    11. ncoghlan commented on Dec 30, 2016

      @ncoghlan
      Contributor

      +1 from me for the general idea.

      One subtlety with the draft implementation is that an Initialize/Finalize cycle doesn't reset the counter, which:

      1. Increases the chance of counter overflow (while admittedly still leaving it incredibly low)
      2. Means you still can't readily check whether the current interpreter is the main interpreter (i.e. the one created automatically in Py_Initialize)

      What do you think about resetting the counter back to 1 in Py_Initialize?

    12. 10 remaining items

    13. vstinner commented on Dec 31, 2016

      @vstinner
      Member

      I would prefer to not use "fast" C types because they are not well supported. For example, ctypes has ctypes.c_int64 but no ctypes.c_int_fast64.

      Previous work adding an unique identifier: PEP-509
      https://www.python.org/dev/peps/pep-0509/#integer-overflow

    14. ericsnowcurrently commented on Dec 31, 2016

      @ericsnowcurrently
      MemberAuthor

      Thanks for pointing that out, Victor. Given the precedent I switched to using int64_t. The patch actually uses PY_INT64_T, but I didn't see a reason to use int64_t directly. FWIW, there *are* a few places that use int_fast64_t, but they are rather specialized and I didn't want this patch to be a place where I had to deal with setting a more general precedent. :)

    15. vstinner commented on May 17, 2017

      @vstinner
      Member

      What the status of this issue Eric? Do you still need interpreter ID?

    16. ericsnowcurrently commented on May 21, 2017

      @ericsnowcurrently
      MemberAuthor

      Yes, I still need it. :)

    17. ericsnowcurrently commented on May 23, 2017

      @ericsnowcurrently
      MemberAuthor

      New changeset e377416 by Eric Snow in branch 'master':
      bpo-29102: Add a unique ID to PyInterpreterState. (bpo-1639)
      e377416

    18. serhiy-storchaka commented on May 23, 2017

      @serhiy-storchaka
      Member

      This change added a compiler warning.

      ./Programs/_testembed.c: In function ‘print_subinterp’:
      ./Programs/_testembed.c:31:22: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘int64_t {aka long long int}’ [-Wformat=]
      printf("interp %lu <0x%" PRIXPTR ">, thread state <0x%" PRIXPTR ">: ",
      ^

    19. ericsnowcurrently commented on May 24, 2017

      @ericsnowcurrently
      MemberAuthor

      Thanks for pointing this out, Serhiy. I'll take a look in the morning.

    20. vstinner commented on May 24, 2017

      @vstinner
      Member

      Does someone know the PRxxx constant for int64_t?

    21. ericsnowcurrently commented on May 24, 2017

      @ericsnowcurrently
      MemberAuthor

      Apparently it is PRId64.

    22. ericsnowcurrently commented on May 24, 2017

      @ericsnowcurrently
      MemberAuthor

      (see bpo-30447)

    23. ericsnowcurrently commented on May 25, 2017

      @ericsnowcurrently
      MemberAuthor

      I've fixed the compiler warning via d1c3c13.

    24. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Labels

    3.7 (EOL)end of lifeinterpreter-core(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions