Skip to content

Commit 458e330

Browse files
authored
gh-127081: lock non-re-entrant *pwent calls in free-threading (#132748)
1 parent 2602d8a commit 458e330

File tree

2 files changed

+22
-5
lines changed

2 files changed

+22
-5
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix libc thread safety issues with :mod:`pwd` by locking access to
2+
``getpwall``.

Modules/pwdmodule.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -301,18 +301,33 @@ pwd_getpwall_impl(PyObject *module)
301301
struct passwd *p;
302302
if ((d = PyList_New(0)) == NULL)
303303
return NULL;
304+
305+
#ifdef Py_GIL_DISABLED
306+
static PyMutex getpwall_mutex = {0};
307+
PyMutex_Lock(&getpwall_mutex);
308+
#endif
309+
int failure = 0;
310+
PyObject *v = NULL;
304311
setpwent();
305312
while ((p = getpwent()) != NULL) {
306-
PyObject *v = mkpwent(module, p);
313+
v = mkpwent(module, p);
307314
if (v == NULL || PyList_Append(d, v) != 0) {
308-
Py_XDECREF(v);
309-
Py_DECREF(d);
310-
endpwent();
311-
return NULL;
315+
/* NOTE: cannot dec-ref here, while holding the mutex. */
316+
failure = 1;
317+
goto done;
312318
}
313319
Py_DECREF(v);
314320
}
321+
322+
done:
315323
endpwent();
324+
#ifdef Py_GIL_DISABLED
325+
PyMutex_Unlock(&getpwall_mutex);
326+
#endif
327+
if (failure) {
328+
Py_XDECREF(v);
329+
Py_CLEAR(d);
330+
}
316331
return d;
317332
}
318333
#endif

0 commit comments

Comments
 (0)