From 85903fb210683df51f342b8bdb28c2dac40827c8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 6 Nov 2024 15:22:53 +0100 Subject: [PATCH 1/2] gh-126316: Use mutexes in the grp module --- ...-11-06-15-23-29.gh-issue-126316.xBcDse.rst | 2 + Modules/grpmodule.c | 65 +++++++++++++++++-- 2 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-11-06-15-23-29.gh-issue-126316.xBcDse.rst diff --git a/Misc/NEWS.d/next/Library/2024-11-06-15-23-29.gh-issue-126316.xBcDse.rst b/Misc/NEWS.d/next/Library/2024-11-06-15-23-29.gh-issue-126316.xBcDse.rst new file mode 100644 index 00000000000000..74cd429e63271e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-11-06-15-23-29.gh-issue-126316.xBcDse.rst @@ -0,0 +1,2 @@ +:mod:`grp`: Fix segfault on concurrent calls on Free Threaded build by using +mutexes. Patch by Victor Stinner. diff --git a/Modules/grpmodule.c b/Modules/grpmodule.c index f7d3e12f347ec2..ca243c61655ee1 100644 --- a/Modules/grpmodule.c +++ b/Modules/grpmodule.c @@ -14,6 +14,22 @@ #include // memcpy() #include // sysconf() +#ifdef Py_GIL_DISABLED +// Need mutexes since getgrgid(), getgrnam() and getgrall() are not +// thread safe (gh-126316). +static PyMutex getgrgid_mutex = {0}; +static PyMutex getgrnam_mutex = {0}; +static PyMutex getgrall_mutex = {0}; + +# define LOCK(mutex) PyMutex_Lock(&(mutex)) +# define UNLOCK(mutex) PyMutex_Unlock(&(mutex)) +#else + // Calls are serialized by the GIL +# define LOCK(mutex) +# define UNLOCK(mutex) +#endif + + #include "clinic/grpmodule.c.h" /*[clinic input] module grp @@ -46,6 +62,13 @@ typedef struct { PyTypeObject *StructGrpType; } grpmodulestate; + +// Forward declarations +static PyObject* grp_getgrgid_unlocked(grpmodulestate *state, PyObject *id); +static PyObject* grp_getgrnam_unlocked(grpmodulestate *state, PyObject *name); +static PyObject* grp_getgrall_unlocked(grpmodulestate *state); + + static inline grpmodulestate* get_grp_state(PyObject *module) { @@ -59,13 +82,13 @@ static struct PyModuleDef grpmodule; #define DEFAULT_BUFFER_SIZE 1024 static PyObject * -mkgrent(PyObject *module, struct group *p) +mkgrent(grpmodulestate *state, struct group *p) { int setIndex = 0; PyObject *v, *w; char **member; - v = PyStructSequence_New(get_grp_state(module)->StructGrpType); + v = PyStructSequence_New(state->StructGrpType); if (v == NULL) return NULL; @@ -123,6 +146,17 @@ If id is not valid, raise KeyError. static PyObject * grp_getgrgid_impl(PyObject *module, PyObject *id) /*[clinic end generated code: output=30797c289504a1ba input=15fa0e2ccf5cda25]*/ +{ + grpmodulestate *state = get_grp_state(module); + LOCK(getgrgid_mutex); + PyObject *res = grp_getgrgid_unlocked(state, id); + UNLOCK(getgrgid_mutex); + return res; +} + + +static PyObject* +grp_getgrgid_unlocked(grpmodulestate *state, PyObject *id) { PyObject *retval = NULL; int nomem = 0; @@ -183,7 +217,7 @@ grp_getgrgid_impl(PyObject *module, PyObject *id) Py_DECREF(gid_obj); return NULL; } - retval = mkgrent(module, p); + retval = mkgrent(state, p); #ifdef HAVE_GETGRGID_R PyMem_RawFree(buf); #endif @@ -203,6 +237,17 @@ If name is not valid, raise KeyError. static PyObject * grp_getgrnam_impl(PyObject *module, PyObject *name) /*[clinic end generated code: output=67905086f403c21c input=08ded29affa3c863]*/ +{ + grpmodulestate *state = get_grp_state(module); + LOCK(getgrnam_mutex); + PyObject *res = grp_getgrnam_unlocked(state, name); + UNLOCK(getgrnam_mutex); + return res; +} + + +static PyObject* +grp_getgrnam_unlocked(grpmodulestate *state, PyObject *name) { char *buf = NULL, *buf2 = NULL, *name_chars; int nomem = 0; @@ -261,7 +306,7 @@ grp_getgrnam_impl(PyObject *module, PyObject *name) } goto out; } - retval = mkgrent(module, p); + retval = mkgrent(state, p); out: PyMem_RawFree(buf); Py_DECREF(bytes); @@ -280,6 +325,16 @@ to use YP/NIS and may not be accessible via getgrnam or getgrgid. static PyObject * grp_getgrall_impl(PyObject *module) /*[clinic end generated code: output=585dad35e2e763d7 input=d7df76c825c367df]*/ +{ + grpmodulestate *state = get_grp_state(module); + LOCK(getgrall_mutex); + PyObject *res = grp_getgrall_unlocked(state); + UNLOCK(getgrall_mutex); + return res; +} + +static PyObject* +grp_getgrall_unlocked(grpmodulestate *state) { PyObject *d; struct group *p; @@ -288,7 +343,7 @@ grp_getgrall_impl(PyObject *module) return NULL; setgrent(); while ((p = getgrent()) != NULL) { - PyObject *v = mkgrent(module, p); + PyObject *v = mkgrent(state, p); if (v == NULL || PyList_Append(d, v) != 0) { Py_XDECREF(v); Py_DECREF(d); From e2f9669e3797fc0d1cfbd84c0cf507201f7d324c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 6 Nov 2024 15:32:55 +0100 Subject: [PATCH 2/2] Update Misc/NEWS.d/next/Library/2024-11-06-15-23-29.gh-issue-126316.xBcDse.rst Co-authored-by: Peter Bierma --- .../next/Library/2024-11-06-15-23-29.gh-issue-126316.xBcDse.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2024-11-06-15-23-29.gh-issue-126316.xBcDse.rst b/Misc/NEWS.d/next/Library/2024-11-06-15-23-29.gh-issue-126316.xBcDse.rst index 74cd429e63271e..b25bb1da109fb3 100644 --- a/Misc/NEWS.d/next/Library/2024-11-06-15-23-29.gh-issue-126316.xBcDse.rst +++ b/Misc/NEWS.d/next/Library/2024-11-06-15-23-29.gh-issue-126316.xBcDse.rst @@ -1,2 +1,2 @@ -:mod:`grp`: Fix segfault on concurrent calls on Free Threaded build by using +:mod:`grp`: Fix segfault on concurrent calls on :term:`free-threaded ` build by using mutexes. Patch by Victor Stinner. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy