cpython: 6b08429a3932 (original) (raw)

Mercurial > cpython

changeset 99391:6b08429a3932

Issue #5319: New Py_FinalizeEx() API to exit with status 120 on failure [#5319]

Martin Panter vadmium+py@gmail.com
date Mon, 30 Nov 2015 03🔞29 +0000
parents c852c7d8d681
children 962086677306
files Doc/c-api/init.rst Doc/c-api/intro.rst Doc/c-api/sys.rst Doc/extending/embedding.rst Doc/includes/run-func.c Doc/library/sys.rst Doc/whatsnew/3.6.rst Include/pylifecycle.h Lib/test/test_cmd_line.py Misc/NEWS Misc/SpecialBuilds.txt Modules/main.c PC/bdist_wininst/install.c PC/python3.def Python/frozenmain.c Python/pylifecycle.c Python/pystate.c Tools/scripts/combinerefs.py
diffstat 18 files changed, 120 insertions(+), 58 deletions(-)[+] [-] Doc/c-api/init.rst 33 Doc/c-api/intro.rst 4 Doc/c-api/sys.rst 14 Doc/extending/embedding.rst 6 Doc/includes/run-func.c 4 Doc/library/sys.rst 7 Doc/whatsnew/3.6.rst 6 Include/pylifecycle.h 1 Lib/test/test_cmd_line.py 3 Misc/NEWS 3 Misc/SpecialBuilds.txt 8 Modules/main.c 8 PC/bdist_wininst/install.c 18 PC/python3.def 1 Python/frozenmain.c 4 Python/pylifecycle.c 52 Python/pystate.c 2 Tools/scripts/combinerefs.py 4

line wrap: on

line diff

--- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -25,7 +25,7 @@ Initializing and finalizing the interpre triple: module; search; path single: PySys_SetArgv() single: PySys_SetArgvEx()

Initialize the Python interpreter. In an application embedding Python, this should be called before using any other Python/C API functions; with the @@ -34,7 +34,7 @@ Initializing and finalizing the interpre modules :mod:builtins, :mod:__main__ and :mod:sys. It also initializes the module search path (sys.path). It does not set sys.argv; use :c:func:PySys_SetArgvEx for that. This is a no-op when called for a second time

@@ -48,19 +48,20 @@ Initializing and finalizing the interpre .. c:function:: int Py_IsInitialized() Return true (nonzero) when the Python interpreter has been initialized, false

-.. c:function:: void Py_Finalize() +.. c:function:: int Py_FinalizeEx() Undo all initializations made by :c:func:Py_Initialize and subsequent use of Python/C API functions, and destroy all sub-interpreters (see :c:func:Py_NewInterpreter below) that were created and not yet destroyed since the last call to :c:func:Py_Initialize. Ideally, this frees all memory allocated by the Python interpreter. This is a no-op when called for a second

+ +.. c:function:: void Py_Finalize() +

Process-wide parameters @@ -107,7 +116,7 @@ Process-wide parameters Note that :data:sys.stderr always uses the "backslashreplace" error handler, regardless of this (or any other) setting.

Extension modules are shared between (sub-)interpreters as follows: the first @@ -928,7 +937,7 @@ using the following functions: and filled with the contents of this copy; the extension's init function is not called. Note that this is different from what happens when an extension is imported after the interpreter has been completely re-initialized by calling

.. c:function:: void Py_EndInterpreter(PyThreadState *tstate)

--- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -578,9 +578,9 @@ Sometimes, it is desirable to "uninitial application may want to start over (make another call to :c:func:Py_Initialize) or the application is simply done with its use of Python and wants to free memory allocated by Python. This can be accomplished -by calling :c:func:Py_Finalize. The function :c:func:Py_IsInitialized returns +by calling :c:func:Py_FinalizeEx. The function :c:func:Py_IsInitialized returns true if Python is currently in the initialized state. More information about -these functions is given in a later chapter. Notice that :c:func:Py_Finalize +these functions is given in a later chapter. Notice that :c:func:Py_FinalizeEx does not free all memory allocated by the Python interpreter, e.g. memory allocated by extension modules currently cannot be released.

--- a/Doc/c-api/sys.rst +++ b/Doc/c-api/sys.rst @@ -212,20 +212,24 @@ Process Control .. c:function:: void Py_Exit(int status) .. index::

.. c:function:: int Py_AtExit(void (*func) ()) .. index::

--- a/Doc/extending/embedding.rst +++ b/Doc/extending/embedding.rst @@ -67,7 +67,9 @@ perform some operation on a file. :: Py_Initialize(); PyRun_SimpleString("from time import time,ctime\n" "print('Today is', ctime(time()))\n");

--- a/Doc/includes/run-func.c +++ b/Doc/includes/run-func.c @@ -63,6 +63,8 @@ main(int argc, char *argv[]) fprintf(stderr, "Failed to load "%s"\n", argv[1]); return 1; }

--- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -255,7 +255,7 @@ always available. (defaulting to zero), or another type of object. If it is an integer, zero is considered "successful termination" and any nonzero value is considered "abnormal termination" by shells and the like. Most systems require it to be

+ .. data:: flags

--- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -171,7 +171,8 @@ Optimizations Build and C API Changes ======================= -* None yet. +* New :c:func:Py_FinalizeEx API which indicates if flushing buffered data

--- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -27,6 +27,7 @@ PyAPI_FUNC(void) Py_InitializeEx(int); PyAPI_FUNC(void) _Py_InitializeEx_Private(int, int); #endif PyAPI_FUNC(void) Py_Finalize(void); +PyAPI_FUNC(int) Py_FinalizeEx(void); PyAPI_FUNC(int) Py_IsInitialized(void); PyAPI_FUNC(PyThreadState *) Py_NewInterpreter(void); PyAPI_FUNC(void) Py_EndInterpreter(PyThreadState *);

--- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -348,8 +348,9 @@ class CmdLineTest(unittest.TestCase): test.support.SuppressCrashReport().enter() sys.stdout.write('x') os.close(sys.stdout.fileno())"""

--- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Release date: XXXX-XX-XX Core and Builtins ----------------- +- Issue #5319: New Py_FinalizeEx() API allowing Python to set an exit status

--- a/Misc/SpecialBuilds.txt +++ b/Misc/SpecialBuilds.txt @@ -65,9 +65,9 @@ sys.getobjects(max[, type]) simply by virtue of being in the list. envvar PYTHONDUMPREFS

Changed in 2.5: The number of extra bytes allocated is 4*sizeof(size_t). Before it was 16 on all boxes, reflecting that Python couldn't make use of @@ -179,7 +179,7 @@ Each type object grows three new members */ int tp_maxalloc; -Allocation and deallocation code keeps these counts up to date. Py_Finalize() +Allocation and deallocation code keeps these counts up to date. Py_FinalizeEx() displays a summary of the info returned by sys.getcounts() (see below), along with assorted other special allocation counts (like the number of tuple allocations satisfied by a tuple free-list, the number of 1-character strings

--- a/Modules/main.c +++ b/Modules/main.c @@ -654,7 +654,7 @@ Py_Main(int argc, wchar_t *argv) Py_SetProgramName(wbuf); / Don't free wbuf, the argument to Py_SetProgramName

@@ -785,7 +785,11 @@ Py_Main(int argc, wchar_t **argv) sts = PyRun_AnyFileFlags(stdin, "", &cf) != 0; }

#ifdef INSURE /* Insure++ is a memory analysis tool that aids in discovering

--- a/PC/bdist_wininst/install.c +++ b/PC/bdist_wininst/install.c @@ -709,7 +709,7 @@ static int prepare_script_environment(HI

@@ -730,7 +730,7 @@ do_run_installscript(HINSTANCE hPython, DECLPROC(hPython, PyObject *, PyErr_Format, (PyObject *, char *)); if (!Py_Initialize || !PySys_SetArgv

if (!Py_BuildValue || !PyArg_ParseTuple || !PyErr_Format) @@ -777,7 +777,9 @@ do_run_installscript(HINSTANCE hPython, } } }

close(fh); return result; @@ -839,11 +841,11 @@ static int do_run_simple_script(HINSTANC int rc; DECLPROC(hPython, void, Py_Initialize, (void)); DECLPROC(hPython, void, Py_SetProgramName, (wchar_t *));

@@ -853,7 +855,9 @@ static int do_run_simple_script(HINSTANC rc = PyRun_SimpleString(script); if (rc) PyErr_Print();

--- a/PC/python3.def +++ b/PC/python3.def @@ -648,6 +648,7 @@ EXPORTS Py_FatalError=python36.Py_FatalError Py_FileSystemDefaultEncoding=python36.Py_FileSystemDefaultEncoding DATA Py_Finalize=python36.Py_Finalize

--- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -99,7 +99,9 @@ Py_FrozenMain(int argc, char **argv) #ifdef MS_WINDOWS PyWinFreeze_ExeTerm(); #endif

error: PyMem_RawFree(argv_copy);

--- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -154,8 +154,8 @@ Py_SetStandardStreamEncoding(const char return 0; } -/* Global initializations. Can be undone by Py_Finalize(). Don't

#ifdef WITH_THREAD

if (fout != NULL && fout != Py_None && !file_is_closed(fout)) { tmp = _PyObject_CallMethodId(fout, &PyId_flush, "");

} /* Undo the effect of Py_Initialize(). @@ -515,14 +522,15 @@ flush_std_files(void) */ -void -Py_Finalize(void) +int +Py_FinalizeEx(void) { PyInterpreterState *interp; PyThreadState *tstate;

if (!initialized)

wait_for_thread_shutdown(); @@ -547,7 +555,9 @@ Py_Finalize(void) initialized = 0; /* Flush sys.stdout and sys.stderr */

/* Disable signal handling / PyOS_FiniInterrupts(); @@ -576,7 +586,9 @@ Py_Finalize(void) PyImport_Cleanup(); / Flush sys.stdout and sys.stderr (again, in case more was printed) */

/* Collect final garbage. This disposes of cycles created by * class definitions, for example. @@ -696,6 +708,13 @@ Py_Finalize(void) #endif call_ll_exitfuncs();

+} + +void +Py_Finalize(void) +{

} /* Create and initialize a new interpreter and thread, and return the @@ -803,7 +822,7 @@ handle_error: frames, and that it is its interpreter's only remaining thread. It is a fatal error to violate these constraints.

@@ -1450,7 +1470,9 @@ call_ll_exitfuncs(void) void Py_Exit(int sts) {

exit(sts); }

--- a/Python/pystate.c +++ b/Python/pystate.c @@ -686,7 +686,7 @@ PyThreadState_IsCurrent(PyThreadState t } / Internal initialization/finalization functions called by

--- a/Tools/scripts/combinerefs.py +++ b/Tools/scripts/combinerefs.py @@ -6,7 +6,7 @@ combinerefs path A helper for analyzing PYTHONDUMPREFS output. When the PYTHONDUMPREFS envar is set in a debug build, at Python shutdown -time Py_Finalize() prints the list of all live objects twice: first it +time Py_FinalizeEx() prints the list of all live objects twice: first it prints the repr() of each object while the interpreter is still fully intact. After cleaning up everything it can, it prints all remaining live objects again, but the second time just prints their addresses, refcounts, and type @@ -41,7 +41,7 @@ CAUTION: If object is a container type, objects shown in the repr: the repr was captured from the first output block, and some of the containees may have been released since then. For example, it's common for the line showing the dict of interned strings to display -strings that no longer exist at the end of Py_Finalize; this can be recognized +strings that no longer exist at the end of Py_FinalizeEx; this can be recognized (albeit painfully) because such containees don't have a line of their own. The objects are listed in allocation order, with most-recently allocated