Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(34229)

Side by Side Diff: Modules/posixmodule.c

Issue 25994: File descriptor leaks in os.scandir()
Patch Set: Created 3 years, 7 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« Doc/whatsnew/3.6.rst ('K') | « Misc/NEWS ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* POSIX module implementation */ 2 /* POSIX module implementation */
3 3
4 /* This file is also used for Windows NT/MS-Win. In that case the 4 /* This file is also used for Windows NT/MS-Win. In that case the
5 module actually calls itself 'nt', not 'posix', and a few 5 module actually calls itself 'nt', not 'posix', and a few
6 functions are either unimplemented or implemented differently. The source 6 functions are either unimplemented or implemented differently. The source
7 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent 7 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
8 of the compiler used. Different compilers define their own feature 8 of the compiler used. Different compilers define their own feature
9 test macro, e.g. '_MSC_VER'. */ 9 test macro, e.g. '_MSC_VER'. */
10 10
(...skipping 11920 matching lines...) Expand 10 before | Expand all | Expand 10 after
11931 WIN32_FIND_DATAW file_data; 11931 WIN32_FIND_DATAW file_data;
11932 int first_time; 11932 int first_time;
11933 #else /* POSIX */ 11933 #else /* POSIX */
11934 DIR *dirp; 11934 DIR *dirp;
11935 #endif 11935 #endif
11936 } ScandirIterator; 11936 } ScandirIterator;
11937 11937
11938 #ifdef MS_WINDOWS 11938 #ifdef MS_WINDOWS
11939 11939
11940 static void 11940 static void
11941 ScandirIterator_close(ScandirIterator *iterator) 11941 ScandirIterator_closedir(ScandirIterator *iterator)
11942 { 11942 {
11943 if (iterator->handle == INVALID_HANDLE_VALUE) 11943 if (iterator->handle == INVALID_HANDLE_VALUE)
11944 return; 11944 return;
11945 11945
11946 Py_BEGIN_ALLOW_THREADS 11946 Py_BEGIN_ALLOW_THREADS
11947 FindClose(iterator->handle); 11947 FindClose(iterator->handle);
11948 Py_END_ALLOW_THREADS 11948 Py_END_ALLOW_THREADS
11949 iterator->handle = INVALID_HANDLE_VALUE; 11949 iterator->handle = INVALID_HANDLE_VALUE;
11950 } 11950 }
11951 11951
11952 static PyObject * 11952 static PyObject *
11953 ScandirIterator_iternext(ScandirIterator *iterator) 11953 ScandirIterator_iternext(ScandirIterator *iterator)
11954 { 11954 {
11955 WIN32_FIND_DATAW *file_data = &iterator->file_data; 11955 WIN32_FIND_DATAW *file_data = &iterator->file_data;
11956 BOOL success; 11956 BOOL success;
11957 PyObject *entry; 11957 PyObject *entry;
11958 11958
11959 /* Happens if the iterator is iterated twice */ 11959 /* Happens if the iterator is iterated twice */
haypo 2016/02/08 23:12:44 You should update the comment. Something like: /*
storchaka 2016/02/09 16:11:45 Done.
11960 if (iterator->handle == INVALID_HANDLE_VALUE) 11960 if (iterator->handle == INVALID_HANDLE_VALUE)
11961 return NULL; 11961 return NULL;
11962 11962
11963 while (1) { 11963 while (1) {
11964 if (!iterator->first_time) { 11964 if (!iterator->first_time) {
11965 Py_BEGIN_ALLOW_THREADS 11965 Py_BEGIN_ALLOW_THREADS
11966 success = FindNextFileW(iterator->handle, file_data); 11966 success = FindNextFileW(iterator->handle, file_data);
11967 Py_END_ALLOW_THREADS 11967 Py_END_ALLOW_THREADS
11968 if (!success) { 11968 if (!success) {
11969 /* Error or no more files */ 11969 /* Error or no more files */
(...skipping 10 matching lines...) Expand all
11980 entry = DirEntry_from_find_data(&iterator->path, file_data); 11980 entry = DirEntry_from_find_data(&iterator->path, file_data);
11981 if (!entry) 11981 if (!entry)
11982 break; 11982 break;
11983 return entry; 11983 return entry;
11984 } 11984 }
11985 11985
11986 /* Loop till we get a non-dot directory or finish iterating */ 11986 /* Loop till we get a non-dot directory or finish iterating */
11987 } 11987 }
11988 11988
11989 /* Error or no more files */ 11989 /* Error or no more files */
11990 ScandirIterator_close(iterator); 11990 ScandirIterator_closedir(iterator);
11991 return NULL; 11991 return NULL;
11992 } 11992 }
11993 11993
11994 #else /* POSIX */ 11994 #else /* POSIX */
11995 11995
11996 static void 11996 static void
11997 ScandirIterator_close(ScandirIterator *iterator) 11997 ScandirIterator_closedir(ScandirIterator *iterator)
11998 { 11998 {
11999 if (!iterator->dirp) 11999 if (!iterator->dirp)
12000 return; 12000 return;
12001 12001
12002 Py_BEGIN_ALLOW_THREADS 12002 Py_BEGIN_ALLOW_THREADS
12003 closedir(iterator->dirp); 12003 closedir(iterator->dirp);
12004 Py_END_ALLOW_THREADS 12004 Py_END_ALLOW_THREADS
12005 iterator->dirp = NULL; 12005 iterator->dirp = NULL;
12006 return; 12006 return;
12007 } 12007 }
12008 12008
12009 static PyObject * 12009 static PyObject *
12010 ScandirIterator_iternext(ScandirIterator *iterator) 12010 ScandirIterator_iternext(ScandirIterator *iterator)
12011 { 12011 {
12012 struct dirent *direntp; 12012 struct dirent *direntp;
12013 Py_ssize_t name_len; 12013 Py_ssize_t name_len;
12014 int is_dot; 12014 int is_dot;
12015 PyObject *entry; 12015 PyObject *entry;
12016 12016
12017 /* Happens if the iterator is iterated twice */ 12017 /* Happens if the iterator is iterated twice */
haypo 2016/02/08 23:12:44 ditto
storchaka 2016/02/09 16:11:45 Done.
12018 if (!iterator->dirp) 12018 if (!iterator->dirp)
12019 return NULL; 12019 return NULL;
12020 12020
12021 while (1) { 12021 while (1) {
12022 errno = 0; 12022 errno = 0;
12023 Py_BEGIN_ALLOW_THREADS 12023 Py_BEGIN_ALLOW_THREADS
12024 direntp = readdir(iterator->dirp); 12024 direntp = readdir(iterator->dirp);
12025 Py_END_ALLOW_THREADS 12025 Py_END_ALLOW_THREADS
12026 12026
12027 if (!direntp) { 12027 if (!direntp) {
(...skipping 16 matching lines...) Expand all
12044 ); 12044 );
12045 if (!entry) 12045 if (!entry)
12046 break; 12046 break;
12047 return entry; 12047 return entry;
12048 } 12048 }
12049 12049
12050 /* Loop till we get a non-dot directory or finish iterating */ 12050 /* Loop till we get a non-dot directory or finish iterating */
12051 } 12051 }
12052 12052
12053 /* Error or no more files */ 12053 /* Error or no more files */
12054 ScandirIterator_close(iterator); 12054 ScandirIterator_closedir(iterator);
12055 return NULL; 12055 return NULL;
12056 } 12056 }
12057 12057
12058 #endif 12058 #endif
12059 12059
12060 static PyObject *
12061 ScandirIterator_close(ScandirIterator *self, PyObject *args)
12062 {
12063 ScandirIterator_closedir(self);
12064 Py_RETURN_NONE;
12065 }
12066
12067 static PyObject *
12068 ScandirIterator_enter(PyObject *self, PyObject *args)
12069 {
12070 Py_INCREF(self);
12071 return self;
12072 }
12073
12074 static PyObject *
12075 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
12076 {
12077 ScandirIterator_closedir(self);
12078 Py_RETURN_NONE;
12079 }
12080
12060 static void 12081 static void
12061 ScandirIterator_dealloc(ScandirIterator *iterator) 12082 ScandirIterator_dealloc(ScandirIterator *iterator)
12062 { 12083 {
12063 ScandirIterator_close(iterator); 12084 ScandirIterator_closedir(iterator);
12064 Py_XDECREF(iterator->path.object); 12085 Py_XDECREF(iterator->path.object);
12065 path_cleanup(&iterator->path); 12086 path_cleanup(&iterator->path);
12066 Py_TYPE(iterator)->tp_free((PyObject *)iterator); 12087 Py_TYPE(iterator)->tp_free((PyObject *)iterator);
12067 } 12088 }
12068 12089
12090 static PyMethodDef ScandirIterator_methods[] = {
12091 {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
12092 {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
12093 {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
haypo 2016/02/08 23:12:44 I tried your patch. It took me 10 min to understan
storchaka 2016/02/09 16:11:45 Good catch!
12094 };
12095
12069 static PyTypeObject ScandirIteratorType = { 12096 static PyTypeObject ScandirIteratorType = {
12070 PyVarObject_HEAD_INIT(NULL, 0) 12097 PyVarObject_HEAD_INIT(NULL, 0)
12071 MODNAME ".ScandirIterator", /* tp_name */ 12098 MODNAME ".ScandirIterator", /* tp_name */
12072 sizeof(ScandirIterator), /* tp_basicsize */ 12099 sizeof(ScandirIterator), /* tp_basicsize */
12073 0, /* tp_itemsize */ 12100 0, /* tp_itemsize */
12074 /* methods */ 12101 /* methods */
12075 (destructor)ScandirIterator_dealloc, /* tp_dealloc */ 12102 (destructor)ScandirIterator_dealloc, /* tp_dealloc */
12076 0, /* tp_print */ 12103 0, /* tp_print */
12077 0, /* tp_getattr */ 12104 0, /* tp_getattr */
12078 0, /* tp_setattr */ 12105 0, /* tp_setattr */
12079 0, /* tp_compare */ 12106 0, /* tp_compare */
12080 0, /* tp_repr */ 12107 0, /* tp_repr */
12081 0, /* tp_as_number */ 12108 0, /* tp_as_number */
12082 0, /* tp_as_sequence */ 12109 0, /* tp_as_sequence */
12083 0, /* tp_as_mapping */ 12110 0, /* tp_as_mapping */
12084 0, /* tp_hash */ 12111 0, /* tp_hash */
12085 0, /* tp_call */ 12112 0, /* tp_call */
12086 0, /* tp_str */ 12113 0, /* tp_str */
12087 0, /* tp_getattro */ 12114 0, /* tp_getattro */
12088 0, /* tp_setattro */ 12115 0, /* tp_setattro */
12089 0, /* tp_as_buffer */ 12116 0, /* tp_as_buffer */
12090 Py_TPFLAGS_DEFAULT, /* tp_flags */ 12117 Py_TPFLAGS_DEFAULT, /* tp_flags */
12091 0, /* tp_doc */ 12118 0, /* tp_doc */
12092 0, /* tp_traverse */ 12119 0, /* tp_traverse */
12093 0, /* tp_clear */ 12120 0, /* tp_clear */
12094 0, /* tp_richcompare */ 12121 0, /* tp_richcompare */
12095 0, /* tp_weaklistoffset */ 12122 0, /* tp_weaklistoffset */
12096 PyObject_SelfIter, /* tp_iter */ 12123 PyObject_SelfIter, /* tp_iter */
12097 (iternextfunc)ScandirIterator_iternext, /* tp_iternext */ 12124 (iternextfunc)ScandirIterator_iternext, /* tp_iternext */
12125 ScandirIterator_methods, /* tp_methods */
12098 }; 12126 };
12099 12127
12100 static PyObject * 12128 static PyObject *
12101 posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs) 12129 posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs)
12102 { 12130 {
12103 ScandirIterator *iterator; 12131 ScandirIterator *iterator;
12104 static char *keywords[] = {"path", NULL}; 12132 static char *keywords[] = {"path", NULL};
12105 #ifdef MS_WINDOWS 12133 #ifdef MS_WINDOWS
12106 wchar_t *path_strW; 12134 wchar_t *path_strW;
12107 #else 12135 #else
(...skipping 1035 matching lines...) Expand 10 before | Expand all | Expand 10 after
13143 PyModule_AddObject(m, "_have_functions", list); 13171 PyModule_AddObject(m, "_have_functions", list);
13144 13172
13145 initialized = 1; 13173 initialized = 1;
13146 13174
13147 return m; 13175 return m;
13148 } 13176 }
13149 13177
13150 #ifdef __cplusplus 13178 #ifdef __cplusplus
13151 } 13179 }
13152 #endif 13180 #endif
OLDNEW
« Doc/whatsnew/3.6.rst ('K') | « Misc/NEWS ('k') | no next file » | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+