@@ -29,7 +29,14 @@ static void CPyFunction_dealloc(CPyFunction *m) {
2929}
3030
3131static PyObject * CPyFunction_repr (CPyFunction * op ) {
32- return PyUnicode_FromFormat ("<function %U at %p>" , op -> func_name , (void * )op );
32+ // Use helper to get name for free threading safety.
33+ PyObject * name = CPyFunction_get_name ((PyObject * )op , NULL );
34+ if (unlikely (name == NULL )) {
35+ return NULL ;
36+ }
37+ PyObject * result = PyUnicode_FromFormat ("<function %U at %p>" , name , (void * )op );
38+ Py_DECREF (name );
39+ return result ;
3340}
3441
3542static PyObject * CPyFunction_call (PyObject * func , PyObject * args , PyObject * kw ) {
@@ -59,13 +66,15 @@ static PyMemberDef CPyFunction_members[] = {
5966PyObject * CPyFunction_get_name (PyObject * op , void * context ) {
6067 (void )context ;
6168 CPyFunction * func = (CPyFunction * )op ;
69+ PyObject * result ;
70+ Py_BEGIN_CRITICAL_SECTION (op );
6271 if (unlikely (func -> func_name == NULL )) {
6372 func -> func_name = PyUnicode_InternFromString (((PyCFunctionObject * )func )-> m_ml -> ml_name );
64- if (unlikely (func -> func_name == NULL ))
65- return NULL ;
6673 }
67- Py_INCREF (func -> func_name );
68- return func -> func_name ;
74+ result = func -> func_name ;
75+ Py_XINCREF (result );
76+ Py_END_CRITICAL_SECTION ();
77+ return result ;
6978}
7079
7180int CPyFunction_set_name (PyObject * op , PyObject * value , void * context ) {
@@ -77,8 +86,13 @@ int CPyFunction_set_name(PyObject *op, PyObject *value, void *context) {
7786 }
7887
7988 Py_INCREF (value );
80- Py_XDECREF (func -> func_name );
89+ // Decref outside critical section, since it could run arbitrary code.
90+ PyObject * old ;
91+ Py_BEGIN_CRITICAL_SECTION (op );
92+ old = func -> func_name ;
8193 func -> func_name = value ;
94+ Py_END_CRITICAL_SECTION ();
95+ Py_XDECREF (old );
8296 return 0 ;
8397}
8498
@@ -232,12 +246,31 @@ PyObject* CPyFunction_New(PyObject *module, const char *filename, const char *fu
232246 PyObject * code = NULL , * op = NULL ;
233247 bool set_self = false;
234248
249+ #ifdef Py_GIL_DISABLED
250+ // Double-checked locking: the common case (type already created) is a
251+ // lock-free atomic load. Only the first-time initialization takes the
252+ // mutex, which serializes concurrent creators.
253+ if (!_Py_atomic_load_ptr_acquire (& CPyFunctionType )) {
254+ static PyMutex type_init_mutex = {0 };
255+ PyMutex_Lock (& type_init_mutex );
256+ if (!CPyFunctionType ) {
257+ PyTypeObject * type = (PyTypeObject * )PyType_FromSpec (& CPyFunction_spec );
258+ if (unlikely (!type )) {
259+ PyMutex_Unlock (& type_init_mutex );
260+ goto err ;
261+ }
262+ _Py_atomic_store_ptr_release (& CPyFunctionType , type );
263+ }
264+ PyMutex_Unlock (& type_init_mutex );
265+ }
266+ #else
235267 if (!CPyFunctionType ) {
236268 CPyFunctionType = (PyTypeObject * )PyType_FromSpec (& CPyFunction_spec );
237269 if (unlikely (!CPyFunctionType )) {
238270 goto err ;
239271 }
240272 }
273+ #endif
241274
242275 method = CPyMethodDef_New (funcname , func , func_flags , func_doc );
243276 if (unlikely (!method )) {
0 commit comments