diff options
author | Victor Stinner <vstinner@python.org> | 2022-01-22 22:22:20 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-22 22:22:20 (GMT) |
commit | 9c8e490b8f9e40a6fe9815be58bacaecab5369ee (patch) | |
tree | c249f59c3fb54dc2efb8c38c53b617f72b02c67e /Modules | |
parent | 1626bf4ac7aef1244e6f886e63a31f7ed65fbd10 (diff) | |
download | cpython-9c8e490b8f9e40a6fe9815be58bacaecab5369ee.zip cpython-9c8e490b8f9e40a6fe9815be58bacaecab5369ee.tar.gz cpython-9c8e490b8f9e40a6fe9815be58bacaecab5369ee.tar.bz2 |
bpo-46417: Clear _io module static objects at exit (GH-30807)
Add _PyIO_Fini() function, called by finalize_interp_clear(). It
clears static objects used by the _io extension module.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_io/_iomodule.c | 137 |
1 files changed, 93 insertions, 44 deletions
diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index b4743fb..116688d 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -666,6 +666,82 @@ struct PyModuleDef _PyIO_Module = { (freefunc)iomodule_free, }; + +static PyTypeObject* static_types[] = { + // Base classes + &PyIOBase_Type, + &PyIncrementalNewlineDecoder_Type, + + // PyIOBase_Type subclasses + &PyBufferedIOBase_Type, + &PyRawIOBase_Type, + &PyTextIOBase_Type, + + // PyBufferedIOBase_Type(PyIOBase_Type) subclasses + &PyBytesIO_Type, + &PyBufferedReader_Type, + &PyBufferedWriter_Type, + &PyBufferedRWPair_Type, + &PyBufferedRandom_Type, + + // PyRawIOBase_Type(PyIOBase_Type) subclasses + &PyFileIO_Type, + &_PyBytesIOBuffer_Type, +#ifdef MS_WINDOWS + &PyWindowsConsoleIO_Type, +#endif + + // PyTextIOBase_Type(PyIOBase_Type) subclasses + &PyStringIO_Type, + &PyTextIOWrapper_Type, +}; + + +void +_PyIO_Fini(void) +{ + for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types) - 1; i >= 0; i--) { + PyTypeObject *exc = static_types[i]; + _PyStaticType_Dealloc(exc); + } + + /* Interned strings */ +#define CLEAR_INTERNED(name) \ + Py_CLEAR(_PyIO_str_ ## name) + + CLEAR_INTERNED(close); + CLEAR_INTERNED(closed); + CLEAR_INTERNED(decode); + CLEAR_INTERNED(encode); + CLEAR_INTERNED(fileno); + CLEAR_INTERNED(flush); + CLEAR_INTERNED(getstate); + CLEAR_INTERNED(isatty); + CLEAR_INTERNED(locale); + CLEAR_INTERNED(newlines); + CLEAR_INTERNED(peek); + CLEAR_INTERNED(read); + CLEAR_INTERNED(read1); + CLEAR_INTERNED(readable); + CLEAR_INTERNED(readall); + CLEAR_INTERNED(readinto); + CLEAR_INTERNED(readline); + CLEAR_INTERNED(reset); + CLEAR_INTERNED(seek); + CLEAR_INTERNED(seekable); + CLEAR_INTERNED(setstate); + CLEAR_INTERNED(tell); + CLEAR_INTERNED(truncate); + CLEAR_INTERNED(write); + CLEAR_INTERNED(writable); +#undef CLEAR_INTERNED + + Py_CLEAR(_PyIO_str_nl); + Py_CLEAR(_PyIO_empty_str); + Py_CLEAR(_PyIO_empty_bytes); +} + + PyMODINIT_FUNC PyInit__io(void) { @@ -676,11 +752,6 @@ PyInit__io(void) state = get_io_state(m); state->initialized = 0; -#define ADD_TYPE(type) \ - if (PyModule_AddType(m, type) < 0) { \ - goto fail; \ - } - /* DEFAULT_BUFFER_SIZE */ if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0) goto fail; @@ -702,57 +773,34 @@ PyInit__io(void) (PyObject *) PyExc_BlockingIOError) < 0) goto fail; - /* Concrete base types of the IO ABCs. - (the ABCs themselves are declared through inheritance in io.py) - */ - ADD_TYPE(&PyIOBase_Type); - ADD_TYPE(&PyRawIOBase_Type); - ADD_TYPE(&PyBufferedIOBase_Type); - ADD_TYPE(&PyTextIOBase_Type); - - /* Implementation of concrete IO objects. */ - /* FileIO */ + // Set type base classes PyFileIO_Type.tp_base = &PyRawIOBase_Type; - ADD_TYPE(&PyFileIO_Type); - - /* BytesIO */ PyBytesIO_Type.tp_base = &PyBufferedIOBase_Type; - ADD_TYPE(&PyBytesIO_Type); - if (PyType_Ready(&_PyBytesIOBuffer_Type) < 0) - goto fail; - - /* StringIO */ PyStringIO_Type.tp_base = &PyTextIOBase_Type; - ADD_TYPE(&PyStringIO_Type); - #ifdef MS_WINDOWS - /* WindowsConsoleIO */ PyWindowsConsoleIO_Type.tp_base = &PyRawIOBase_Type; - ADD_TYPE(&PyWindowsConsoleIO_Type); #endif - - /* BufferedReader */ PyBufferedReader_Type.tp_base = &PyBufferedIOBase_Type; - ADD_TYPE(&PyBufferedReader_Type); - - /* BufferedWriter */ PyBufferedWriter_Type.tp_base = &PyBufferedIOBase_Type; - ADD_TYPE(&PyBufferedWriter_Type); - - /* BufferedRWPair */ PyBufferedRWPair_Type.tp_base = &PyBufferedIOBase_Type; - ADD_TYPE(&PyBufferedRWPair_Type); - - /* BufferedRandom */ PyBufferedRandom_Type.tp_base = &PyBufferedIOBase_Type; - ADD_TYPE(&PyBufferedRandom_Type); - - /* TextIOWrapper */ PyTextIOWrapper_Type.tp_base = &PyTextIOBase_Type; - ADD_TYPE(&PyTextIOWrapper_Type); - /* IncrementalNewlineDecoder */ - ADD_TYPE(&PyIncrementalNewlineDecoder_Type); + // Add types + for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) { + PyTypeObject *type = static_types[i]; + // Private type not exposed in the _io module + if (type == &_PyBytesIOBuffer_Type) { + if (PyType_Ready(type) < 0) { + goto fail; + } + } + else { + if (PyModule_AddType(m, type) < 0) { + goto fail; + } + } + } /* Interned strings */ #define ADD_INTERNED(name) \ @@ -785,6 +833,7 @@ PyInit__io(void) ADD_INTERNED(truncate) ADD_INTERNED(write) ADD_INTERNED(writable) +#undef ADD_INTERNED if (!_PyIO_str_nl && !(_PyIO_str_nl = PyUnicode_InternFromString("\n"))) |