Skip to content

remove sys.exitfunc, rewrite atexit in C #44715

Closed

Description

@birkenfeld
BPO 1680961
Nosy @birkenfeld, @pitrou, @dhellmann
Files
  • atexit.diff: patch
  • atexit.patch: Alternate atexit implementation, v3
  • 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 = None
    closed_at = <Date 2013-08-18.23:08:49.231>
    created_at = <Date 2007-03-14.19:51:10.000>
    labels = ['interpreter-core']
    title = 'remove sys.exitfunc, rewrite atexit in C'
    updated_at = <Date 2013-08-18.23:08:49.231>
    user = 'https://github.com/birkenfeld'

    bugs.python.org fields:

    activity = <Date 2013-08-18.23:08:49.231>
    actor = 'doughellmann'
    assignee = 'none'
    closed = True
    closed_date = None
    closer = None
    components = ['Interpreter Core']
    creation = <Date 2007-03-14.19:51:10.000>
    creator = 'georg.brandl'
    dependencies = []
    files = ['7869', '7870']
    hgrepos = []
    issue_num = 1680961
    keywords = ['patch']
    message_count = 21.0
    messages = ['52197', '52198', '52199', '52200', '52201', '52202', '52203', '52204', '52205', '52206', '52207', '52208', '52209', '52210', '52211', '52212', '52213', '52214', '52215', '52216', '195585']
    nosy_count = 5.0
    nosy_names = ['georg.brandl', 'collinwinter', 'alanmcintyre', 'pitrou', 'doughellmann']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue1680961'
    versions = ['Python 3.0']

    Activity

    1. birkenfeld commented on Mar 14, 2007

      @birkenfeld
      MemberAuthor

      This removes sys.exitfunc. atexit is rewritten in C and uses as much of the existing sys.exitfunc-infrastructure (which is renamed).

    2. alanmcintyre commented on Mar 14, 2007

      alanmcintyremannequin
      Mannequin

      The attached patch didn't apply cleanly for me; the hunk that removes call_sys_exitfunc (pythonrun.c) failed, but everything else applied just fine. I removed call_sys_exitfunc manually and then everything compiled and passes regrtest.py (with -r -u all) with no unexpected skips (Linux).

      The docs also build just fine and I don't see any grammatical/formatting errors or anything that jumps out as a technical error (but I'm not all that familiar with atexit/exitfunc, so take my endorsement with a grain of salt ;).

    3. birkenfeld commented on Mar 14, 2007

      @birkenfeld
      MemberAuthor

      Note that the patch is against the p3yk branch.

      Note also that, without changing Modules/Setup, the new module won't be built and used.
      In fact, the test suite doesn't pass with it since I haven't updated the tests that
      depend on atexit._exithandlers.

      But thanks for reviewing nonetheless!

    4. collinwinter commented on Mar 15, 2007

      collinwintermannequin
      Mannequin

      Ack, I didn't know you were working on this, too! I'm attaching my own atexit implementation; the patch includes changes to Modules/Setup, test_atexit and test___all__ so that the test suite passes.

      One thing I'm not sure about is that I've moved call_ll_exitfuncs() up in the order of Py_Finalize(). This was necessary to make PyThreadState_GET() stop complaining about "no current thread" when calling the atexit functions at interpreter-shutdown, but I don't know enough to be sure that this change doesn't alter some assumption about finalization order. It looks alright to me, and "make test" passes, but I'd appreciate it if someone could look over that part.
      File Added: atexit.patch

    5. birkenfeld commented on Mar 15, 2007

      @birkenfeld
      MemberAuthor

      To summarize the differences: your code uses a C array to store the exit handlers, mine uses a Python list.
      Which to choose obviously depends on whether you want to make the list available to Python code...

    6. collinwinter commented on Mar 15, 2007

      collinwintermannequin
      Mannequin

      Another difference: mine uses Py_AtExit(), yours adds extra C functions like Py_SetPythonExitfunc() and call_python_exitfunc().

      I'd vote against exposing the handler list to Python code. I see that leading to "run my handler first! No, mine! *scuffle*" games.

    7. birkenfeld commented on Mar 15, 2007

      @birkenfeld
      MemberAuthor

      What about a function to get a *copy* of the exitfuncs? (Okay, I can't see a use case right now, but maybe it helps transitioning code that inspected atexit._exithandlers before)

    8. collinwinter commented on Mar 15, 2007

      collinwintermannequin
      Mannequin

      Googling turns up that the main use of atexit._exithandlers is to a) unregister a callback or b) clear all callbacks. I've already provided a _clear() function to handle (b), and an unregister() to deal with (a) shouldn't be hard. Thoughts?

    9. birkenfeld commented on Mar 15, 2007

      @birkenfeld
      MemberAuthor

      Yes, that would work for me.

      The issue I see with moving the low-level exitfuncs that is that the functions registered there may
      make resources unavailable that are necessary for Python code to run (and of course, atexit handlers
      can run arbitrary Python code...)

    10. collinwinter commented on Mar 15, 2007

      collinwintermannequin
      Mannequin

      Isn't that (unavailable resources) a problem with atexit handlers in general, regardless of where they occur in Py_Finalize()? All existing low-level exitfuncs are already guaranteed not to mess with interpreter/thread state, simply because they can't (as things stand). If exitfuncs written against 3.0+ start messing around with Python's internal state, that's a bug in the exitfunc. We're all adults, etc.

      I'm attaching the new version of my patch, which includes atexit.unregister().
      File Added: atexit.patch

    11. birkenfeld commented on Mar 15, 2007

      @birkenfeld
      MemberAuthor

      For example, Modules/socketmodule.c's Py_AtExit handler, for Windows, calls WSACleanup(), after which, if I understand the docs correctly, one can't use sockets anymore.

      That would mean that if atexit is imported before socket, all atexit-registered exitfuncs cannot use sockets.

    12. collinwinter commented on Mar 15, 2007

      collinwintermannequin
      Mannequin

      Doesn't that problem already exist, though, for C extensions that need sockets (or other resources) in their Py_AtExit handlers?

      Would changing call_ll_exitfuncs() from FIFO to LIFO (like atexit is) help this?

    13. birkenfeld commented on Mar 15, 2007

      @birkenfeld
      MemberAuthor

      Current AtExit handlers are not likely to use functionality not in their domain, though.
      The socket one just cleans up the socket API, the Tkinter one (which is disabled though) cleans up Tcl, etc.

      I thought call_ll_exitfuncs() is already LIFO.

    14. collinwinter commented on Mar 15, 2007

      collinwintermannequin
      Mannequin

      It is LIFO; I was going off memory, sorry.

      Is your assumption that atexit.py handlers will be more likely to use functionality outside their domain than would Py_AtExit handlers?

    15. birkenfeld commented on Mar 16, 2007

      @birkenfeld
      MemberAuthor

      It's not specified that exit handlers can do cleanup only, in theory they could do things like sending an email etc.

      Please let's not introduce gratuitous breakage here.

    16. collinwinter commented on Mar 16, 2007

      collinwintermannequin
      Mannequin

      Ok, I'm sold on the two-phase atexit structure. I've updated my patch to keep atexit's handlers separate from the call_ll_exitfuncs() handlers.
      File Added: atexit.patch

    17. birkenfeld commented on Mar 17, 2007

      @birkenfeld
      MemberAuthor

      Looks good, four points:

      • should _clear keep its underscore?
      • unregistering will fail with bound methods, don't know if we should do something about that
      • you messed up the indentation in pythonrun.c and atexit.c (spaces in the former and tabs in the latter) ;)
      • do we need docs for Py_PyAtExit? If not, it should be nonpublic and get a leading underscore.
    18. collinwinter commented on Mar 18, 2007

      collinwintermannequin
      Mannequin
      • I think _clear() should keep the underscore; it's probably not something that people should be encouraged to use.
      • I've fixed bound method support.
      • I'm going to make Py_PyAtExit non-public.
    19. birkenfeld commented on Mar 19, 2007

      @birkenfeld
      MemberAuthor

      You didn't attach a patch, but if you do these modification, you can check it in directly IMO.

    20. collinwinter commented on Mar 21, 2007

      collinwintermannequin
      Mannequin

      Checked in as r54472.

    21. pitrou commented on Aug 18, 2013

      @pitrou
      Member

      Sorry to ping you on an old issue, but can any of you explain why it was necessary to rewrite atexit in C?

    22. 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

    Assignees

    No one assigned

      Labels

      interpreter-core(Objects, Python, Grammar, and Parser dirs)

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions