[Python-checkins] cpython: Implement finalizer for os.scandir() iterator

victor.stinner python-checkins at python.org
Tue Mar 22 19:44:15 EDT 2016


https://hg.python.org/cpython/rev/b65d783cfe3b
changeset:   100670:b65d783cfe3b
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Wed Mar 23 00:43:54 2016 +0100
summary:
  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

files:
  Modules/posixmodule.c |  74 +++++++++++++++++++++---------
  1 files changed, 52 insertions(+), 22 deletions(-)


diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -12101,29 +12101,38 @@
 }
 
 static void
+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)) {
+        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)) {
+                PyErr_WriteUnraisable((PyObject *) iterator);
+            }
+        }
+    }
+
+    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 (!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)) {
-            /* Spurious errors can appear at shutdown */
-            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);
-    path_cleanup(&iterator->path);
+    if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
+        return;
+
     Py_TYPE(iterator)->tp_free((PyObject *)iterator);
 }
 
@@ -12155,7 +12164,8 @@
     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 @@
     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 *

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list