diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2016-03-22 23:43:54 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2016-03-22 23:43:54 (GMT) |
commit | 7bfa409ff841fd84dfa194dd9052650d0a28585d (patch) | |
tree | b278b5b748e99e162101cbdf0a6bd59ad56e0159 | |
parent | e19558af1b6979edf27f7a05a6e47a8b5d113390 (diff) | |
download | cpython-7bfa409ff841fd84dfa194dd9052650d0a28585d.zip cpython-7bfa409ff841fd84dfa194dd9052650d0a28585d.tar.gz cpython-7bfa409ff841fd84dfa194dd9052650d0a28585d.tar.bz2 |
Implement finalizer for os.scandir() iterator
Issue #26603:
* Implement finalizer for os.scandir() iterator
* Set the source parameter when emitting the ResourceWarning warning
* Close the iterator before emitting the warning
-rw-r--r-- | Modules/posixmodule.c | 64 |
1 files changed, 47 insertions, 17 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 65b20be..1cd0f24 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -12101,29 +12101,38 @@ ScandirIterator_exit(ScandirIterator *self, PyObject *args) } static void -ScandirIterator_dealloc(ScandirIterator *iterator) +ScandirIterator_finalize(ScandirIterator *iterator) { + PyObject *error_type, *error_value, *error_traceback; + + /* Save the current exception, if any. */ + PyErr_Fetch(&error_type, &error_value, &error_traceback); + if (!ScandirIterator_is_closed(iterator)) { - PyObject *exc, *val, *tb; - Py_ssize_t old_refcount = Py_REFCNT(iterator); - /* Py_INCREF/Py_DECREF cannot be used, because the refcount is - * likely zero, Py_DECREF would call again the destructor. - */ - ++Py_REFCNT(iterator); - PyErr_Fetch(&exc, &val, &tb); - if (PyErr_WarnFormat(PyExc_ResourceWarning, 1, - "unclosed scandir iterator %R", iterator)) { + ScandirIterator_closedir(iterator); + + if (PyErr_ResourceWarning((PyObject *)iterator, 1, + "unclosed scandir iterator %R", iterator)) { /* Spurious errors can appear at shutdown */ - if (PyErr_ExceptionMatches(PyExc_Warning)) + if (PyErr_ExceptionMatches(PyExc_Warning)) { PyErr_WriteUnraisable((PyObject *) iterator); + } } - PyErr_Restore(exc, val, tb); - Py_REFCNT(iterator) = old_refcount; - - ScandirIterator_closedir(iterator); } - Py_XDECREF(iterator->path.object); + + Py_CLEAR(iterator->path.object); path_cleanup(&iterator->path); + + /* Restore the saved exception. */ + PyErr_Restore(error_type, error_value, error_traceback); +} + +static void +ScandirIterator_dealloc(ScandirIterator *iterator) +{ + if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0) + return; + Py_TYPE(iterator)->tp_free((PyObject *)iterator); } @@ -12155,7 +12164,8 @@ static PyTypeObject ScandirIteratorType = { 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT + | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ @@ -12164,6 +12174,26 @@ static PyTypeObject ScandirIteratorType = { PyObject_SelfIter, /* tp_iter */ (iternextfunc)ScandirIterator_iternext, /* tp_iternext */ ScandirIterator_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ + 0, /* tp_del */ + 0, /* tp_version_tag */ + (destructor)ScandirIterator_finalize, /* tp_finalize */ }; static PyObject * |