Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7bfa409

Browse files
committed
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
1 parent e19558a commit 7bfa409

1 file changed

Lines changed: 47 additions & 17 deletions

File tree

Modules/posixmodule.c

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12101,29 +12101,38 @@ ScandirIterator_exit(ScandirIterator *self, PyObject *args)
1210112101
}
1210212102

1210312103
static void
12104-
ScandirIterator_dealloc(ScandirIterator *iterator)
12104+
ScandirIterator_finalize(ScandirIterator *iterator)
1210512105
{
12106+
PyObject *error_type, *error_value, *error_traceback;
12107+
12108+
/* Save the current exception, if any. */
12109+
PyErr_Fetch(&error_type, &error_value, &error_traceback);
12110+
1210612111
if (!ScandirIterator_is_closed(iterator)) {
12107-
PyObject *exc, *val, *tb;
12108-
Py_ssize_t old_refcount = Py_REFCNT(iterator);
12109-
/* Py_INCREF/Py_DECREF cannot be used, because the refcount is
12110-
* likely zero, Py_DECREF would call again the destructor.
12111-
*/
12112-
++Py_REFCNT(iterator);
12113-
PyErr_Fetch(&exc, &val, &tb);
12114-
if (PyErr_WarnFormat(PyExc_ResourceWarning, 1,
12115-
"unclosed scandir iterator %R", iterator)) {
12112+
ScandirIterator_closedir(iterator);
12113+
12114+
if (PyErr_ResourceWarning((PyObject *)iterator, 1,
12115+
"unclosed scandir iterator %R", iterator)) {
1211612116
/* Spurious errors can appear at shutdown */
12117-
if (PyErr_ExceptionMatches(PyExc_Warning))
12117+
if (PyErr_ExceptionMatches(PyExc_Warning)) {
1211812118
PyErr_WriteUnraisable((PyObject *) iterator);
12119+
}
1211912120
}
12120-
PyErr_Restore(exc, val, tb);
12121-
Py_REFCNT(iterator) = old_refcount;
12122-
12123-
ScandirIterator_closedir(iterator);
1212412121
}
12125-
Py_XDECREF(iterator->path.object);
12122+
12123+
Py_CLEAR(iterator->path.object);
1212612124
path_cleanup(&iterator->path);
12125+
12126+
/* Restore the saved exception. */
12127+
PyErr_Restore(error_type, error_value, error_traceback);
12128+
}
12129+
12130+
static void
12131+
ScandirIterator_dealloc(ScandirIterator *iterator)
12132+
{
12133+
if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
12134+
return;
12135+
1212712136
Py_TYPE(iterator)->tp_free((PyObject *)iterator);
1212812137
}
1212912138

@@ -12155,7 +12164,8 @@ static PyTypeObject ScandirIteratorType = {
1215512164
0, /* tp_getattro */
1215612165
0, /* tp_setattro */
1215712166
0, /* tp_as_buffer */
12158-
Py_TPFLAGS_DEFAULT, /* tp_flags */
12167+
Py_TPFLAGS_DEFAULT
12168+
| Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
1215912169
0, /* tp_doc */
1216012170
0, /* tp_traverse */
1216112171
0, /* tp_clear */
@@ -12164,6 +12174,26 @@ static PyTypeObject ScandirIteratorType = {
1216412174
PyObject_SelfIter, /* tp_iter */
1216512175
(iternextfunc)ScandirIterator_iternext, /* tp_iternext */
1216612176
ScandirIterator_methods, /* tp_methods */
12177+
0, /* tp_members */
12178+
0, /* tp_getset */
12179+
0, /* tp_base */
12180+
0, /* tp_dict */
12181+
0, /* tp_descr_get */
12182+
0, /* tp_descr_set */
12183+
0, /* tp_dictoffset */
12184+
0, /* tp_init */
12185+
0, /* tp_alloc */
12186+
0, /* tp_new */
12187+
0, /* tp_free */
12188+
0, /* tp_is_gc */
12189+
0, /* tp_bases */
12190+
0, /* tp_mro */
12191+
0, /* tp_cache */
12192+
0, /* tp_subclasses */
12193+
0, /* tp_weaklist */
12194+
0, /* tp_del */
12195+
0, /* tp_version_tag */
12196+
(destructor)ScandirIterator_finalize, /* tp_finalize */
1216712197
};
1216812198

1216912199
static PyObject *

0 commit comments

Comments
 (0)