bpo-33625: Release GIL for grp.getgr{nam,gid} and pwd.getpw{nam,uid} … · python/cpython@23e65b2 (original) (raw)
`@@ -50,6 +50,8 @@ exception is raised if the entry asked for cannot be found.");
`
50
50
`static int initialized;
`
51
51
`static PyTypeObject StructPwdType;
`
52
52
``
``
53
`+
#define DEFAULT_BUFFER_SIZE 1024
`
``
54
+
53
55
`static void
`
54
56
`sets(PyObject v, int i, const char val)
`
55
57
`{
`
`@@ -116,16 +118,59 @@ static PyObject *
`
116
118
`pwd_getpwuid(PyObject *module, PyObject *uidobj)
`
117
119
`/[clinic end generated code: output=c4ee1d4d429b86c4 input=ae64d507a1c6d3e8]/
`
118
120
`{
`
``
121
`+
PyObject *retval = NULL;
`
119
122
`uid_t uid;
`
``
123
`+
int nomem = 0;
`
120
124
`struct passwd *p;
`
``
125
`+
char *buf = NULL, *buf2 = NULL;
`
121
126
``
122
127
`if (!_Py_Uid_Converter(uidobj, &uid)) {
`
123
128
`if (PyErr_ExceptionMatches(PyExc_OverflowError))
`
124
129
`PyErr_Format(PyExc_KeyError,
`
125
130
`"getpwuid(): uid not found");
`
126
131
`return NULL;
`
127
132
` }
`
128
``
`-
if ((p = getpwuid(uid)) == NULL) {
`
``
133
`+
#ifdef HAVE_GETPWUID_R
`
``
134
`+
Py_BEGIN_ALLOW_THREADS
`
``
135
`+
int status;
`
``
136
`+
Py_ssize_t bufsize;
`
``
137
`+
struct passwd pwd;
`
``
138
+
``
139
`+
bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
`
``
140
`+
if (bufsize == -1) {
`
``
141
`+
bufsize = DEFAULT_BUFFER_SIZE;
`
``
142
`+
}
`
``
143
+
``
144
`+
while(1) {
`
``
145
`+
buf2 = PyMem_RawRealloc(buf, bufsize);
`
``
146
`+
if (buf2 == NULL) {
`
``
147
`+
nomem = 1;
`
``
148
`+
break;
`
``
149
`+
}
`
``
150
`+
buf = buf2;
`
``
151
`+
status = getpwuid_r(uid, &pwd, buf, bufsize, &p);
`
``
152
`+
if (status != 0) {
`
``
153
`+
p = NULL;
`
``
154
`+
}
`
``
155
`+
if (p != NULL || status != ERANGE) {
`
``
156
`+
break;
`
``
157
`+
}
`
``
158
`+
if (bufsize > (PY_SSIZE_T_MAX >> 1)) {
`
``
159
`+
nomem = 1;
`
``
160
`+
break;
`
``
161
`+
}
`
``
162
`+
bufsize <<= 1;
`
``
163
`+
}
`
``
164
+
``
165
`+
Py_END_ALLOW_THREADS
`
``
166
`+
#else
`
``
167
`+
p = getpwuid(uid);
`
``
168
`+
#endif
`
``
169
`+
if (p == NULL) {
`
``
170
`+
PyMem_RawFree(buf);
`
``
171
`+
if (nomem == 1) {
`
``
172
`+
return PyErr_NoMemory();
`
``
173
`+
}
`
129
174
`PyObject *uid_obj = _PyLong_FromUid(uid);
`
130
175
`if (uid_obj == NULL)
`
131
176
`return NULL;
`
`@@ -134,7 +179,11 @@ pwd_getpwuid(PyObject *module, PyObject *uidobj)
`
134
179
`Py_DECREF(uid_obj);
`
135
180
`return NULL;
`
136
181
` }
`
137
``
`-
return mkpwent(p);
`
``
182
`+
retval = mkpwent(p);
`
``
183
`+
#ifdef HAVE_GETPWUID_R
`
``
184
`+
PyMem_RawFree(buf);
`
``
185
`+
#endif
`
``
186
`+
return retval;
`
138
187
`}
`
139
188
``
140
189
`/*[clinic input]
`
`@@ -152,7 +201,8 @@ static PyObject *
`
152
201
`pwd_getpwnam_impl(PyObject *module, PyObject *arg)
`
153
202
`/[clinic end generated code: output=6abeee92430e43d2 input=d5f7e700919b02d3]/
`
154
203
`{
`
155
``
`-
char *name;
`
``
204
`+
char *buf = NULL, *buf2 = NULL, *name;
`
``
205
`+
int nomem = 0;
`
156
206
`struct passwd *p;
`
157
207
`PyObject *bytes, *retval = NULL;
`
158
208
``
`@@ -161,13 +211,55 @@ pwd_getpwnam_impl(PyObject *module, PyObject *arg)
`
161
211
`/* check for embedded null bytes */
`
162
212
`if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1)
`
163
213
` goto out;
`
164
``
`-
if ((p = getpwnam(name)) == NULL) {
`
165
``
`-
PyErr_Format(PyExc_KeyError,
`
166
``
`-
"getpwnam(): name not found: %s", name);
`
``
214
`+
#ifdef HAVE_GETPWNAM_R
`
``
215
`+
Py_BEGIN_ALLOW_THREADS
`
``
216
`+
int status;
`
``
217
`+
Py_ssize_t bufsize;
`
``
218
`+
struct passwd pwd;
`
``
219
+
``
220
`+
bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
`
``
221
`+
if (bufsize == -1) {
`
``
222
`+
bufsize = DEFAULT_BUFFER_SIZE;
`
``
223
`+
}
`
``
224
+
``
225
`+
while(1) {
`
``
226
`+
buf2 = PyMem_RawRealloc(buf, bufsize);
`
``
227
`+
if (buf2 == NULL) {
`
``
228
`+
nomem = 1;
`
``
229
`+
break;
`
``
230
`+
}
`
``
231
`+
buf = buf2;
`
``
232
`+
status = getpwnam_r(name, &pwd, buf, bufsize, &p);
`
``
233
`+
if (status != 0) {
`
``
234
`+
p = NULL;
`
``
235
`+
}
`
``
236
`+
if (p != NULL || status != ERANGE) {
`
``
237
`+
break;
`
``
238
`+
}
`
``
239
`+
if (bufsize > (PY_SSIZE_T_MAX >> 1)) {
`
``
240
`+
nomem = 1;
`
``
241
`+
break;
`
``
242
`+
}
`
``
243
`+
bufsize <<= 1;
`
``
244
`+
}
`
``
245
+
``
246
`+
Py_END_ALLOW_THREADS
`
``
247
`+
#else
`
``
248
`+
p = getpwnam(name);
`
``
249
`+
#endif
`
``
250
`+
if (p == NULL) {
`
``
251
`+
if (nomem == 1) {
`
``
252
`+
PyErr_NoMemory();
`
``
253
`+
}
`
``
254
`+
else {
`
``
255
`+
PyErr_Format(PyExc_KeyError,
`
``
256
`+
"getpwnam(): name not found: %s", name);
`
``
257
`+
}
`
167
258
` goto out;
`
168
259
` }
`
169
260
`retval = mkpwent(p);
`
170
261
`out:
`
``
262
`+
PyMem_RawFree(buf);
`
171
263
`Py_DECREF(bytes);
`
172
264
`return retval;
`
173
265
`}
`