This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author vstinner
Recipients eric.snow, nascheme, pablogsal, pitrou, serhiy.storchaka, vstinner
Date 2019-09-12.09:27:31
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1568280452.15.0.878770501973.issue32312@roundup.psfhosted.org>
In-reply-to
Content
Joannah Nanjekye asked me to have a look at this issue.

The existing Py_AtExit() C function is very low-level: it's called very late in Py_Finalize(), when the Python runtime is already destroyed.

I understand that the need here is to call C code which would still like to access the Python C API.

I propose the following C API:

   void Py_AtExitRegister(PyObject* (*func) (void *data), void *data)

which would call func(data).

The return type is void since I don't see any practical way to log an useful warning if a function fails: we only gets its memory address, we cannot log that. The callback function ('func') should be responsible to log errors itself (ex: using PySys_WriteStderr which writes into sys.stderr).


Neil:
> It would be handy to have a C API that registered an atexit function, similar to what calling atexit.register does.  This API could be used by C extension modules to register atexit functions.


The PyModuleDef already has 2 slots to call code at Python exit:
  void m_clear(PyObject *module)
and:
  void m_free(void *data).

But these callbacks can be late in Py_Finalize(), while Python runtime is being destroyed: when all modules are unloaded.

atexit.register() callbacks are different: they are called "early" in Py_Finalize(), when Python is still fully working.

I guess that Py_AtExitRegister() callbacks should also be called when Python is still fully working, right?

Apart C extensions, Py_AtExitRegister() also sounds interesting when Python is embedded in an application. For example, if you call Py_Main() or Py_RunMain(), you cannot easily execute arbitrary C code just before Py_Finalize().



Antoine:
> Calling "atexit.register" using the C API isn't very difficult. The annoying part is to wrap a simple C function pointer in a callable PyObject (I don't think there is a simple C API for that).

We could store C callbacks as C function pointers. We can have 2 lists of functions in the atexit module: one for Python function, one for C functions (registered using the C API). I would suggest to call Python functions first, and then call C functions.

--

I changed my mind, and I now consider that adding a public function would be useful. Sorry, first I misunderstood the use cases.
History
Date User Action Args
2019-09-12 09:27:32vstinnersetrecipients: + vstinner, nascheme, pitrou, eric.snow, serhiy.storchaka, pablogsal
2019-09-12 09:27:32vstinnersetmessageid: <1568280452.15.0.878770501973.issue32312@roundup.psfhosted.org>
2019-09-12 09:27:32vstinnerlinkissue32312 messages
2019-09-12 09:27:31vstinnercreate