mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	gh-125221: Fix free-threading data race in object.__reduce_ex__ (#125267)
				
					
				
			This commit is contained in:
		
							parent
							
								
									c1913effee
								
							
						
					
					
						commit
						b12e99261e
					
				
					 3 changed files with 15 additions and 15 deletions
				
			
		| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					Fix possible race condition when calling :meth:`~object.__reduce_ex__` for the
 | 
				
			||||||
 | 
					first time in the free threading build.
 | 
				
			||||||
| 
						 | 
					@ -2372,6 +2372,14 @@ _PyTypes_InitTypes(PyInterpreterState *interp)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Cache __reduce__ from PyBaseObject_Type object
 | 
				
			||||||
 | 
					    PyObject *baseobj_dict = _PyType_GetDict(&PyBaseObject_Type);
 | 
				
			||||||
 | 
					    PyObject *baseobj_reduce = PyDict_GetItemWithError(baseobj_dict, &_Py_ID(__reduce__));
 | 
				
			||||||
 | 
					    if (baseobj_reduce == NULL && PyErr_Occurred()) {
 | 
				
			||||||
 | 
					        return _PyStatus_ERR("Can't get __reduce__ from base object");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    _Py_INTERP_CACHED_OBJECT(interp, objreduce) = baseobj_reduce;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Must be after static types are initialized
 | 
					    // Must be after static types are initialized
 | 
				
			||||||
    if (_Py_initialize_generic(interp) < 0) {
 | 
					    if (_Py_initialize_generic(interp) < 0) {
 | 
				
			||||||
        return _PyStatus_ERR("Can't initialize generic types");
 | 
					        return _PyStatus_ERR("Can't initialize generic types");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7359,18 +7359,7 @@ static PyObject *
 | 
				
			||||||
object___reduce_ex___impl(PyObject *self, int protocol)
 | 
					object___reduce_ex___impl(PyObject *self, int protocol)
 | 
				
			||||||
/*[clinic end generated code: output=2e157766f6b50094 input=f326b43fb8a4c5ff]*/
 | 
					/*[clinic end generated code: output=2e157766f6b50094 input=f326b43fb8a4c5ff]*/
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#define objreduce \
 | 
					    PyObject *reduce;
 | 
				
			||||||
    (_Py_INTERP_CACHED_OBJECT(_PyInterpreterState_GET(), objreduce))
 | 
					 | 
				
			||||||
    PyObject *reduce, *res;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (objreduce == NULL) {
 | 
					 | 
				
			||||||
        PyObject *dict = lookup_tp_dict(&PyBaseObject_Type);
 | 
					 | 
				
			||||||
        objreduce = PyDict_GetItemWithError(dict, &_Py_ID(__reduce__));
 | 
					 | 
				
			||||||
        if (objreduce == NULL && PyErr_Occurred()) {
 | 
					 | 
				
			||||||
            return NULL;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (PyObject_GetOptionalAttr(self, &_Py_ID(__reduce__), &reduce) < 0) {
 | 
					    if (PyObject_GetOptionalAttr(self, &_Py_ID(__reduce__), &reduce) < 0) {
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -7384,10 +7373,12 @@ object___reduce_ex___impl(PyObject *self, int protocol)
 | 
				
			||||||
            Py_DECREF(reduce);
 | 
					            Py_DECREF(reduce);
 | 
				
			||||||
            return NULL;
 | 
					            return NULL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        override = (clsreduce != objreduce);
 | 
					
 | 
				
			||||||
 | 
					        PyInterpreterState *interp = _PyInterpreterState_GET();
 | 
				
			||||||
 | 
					        override = (clsreduce != _Py_INTERP_CACHED_OBJECT(interp, objreduce));
 | 
				
			||||||
        Py_DECREF(clsreduce);
 | 
					        Py_DECREF(clsreduce);
 | 
				
			||||||
        if (override) {
 | 
					        if (override) {
 | 
				
			||||||
            res = _PyObject_CallNoArgs(reduce);
 | 
					            PyObject *res = _PyObject_CallNoArgs(reduce);
 | 
				
			||||||
            Py_DECREF(reduce);
 | 
					            Py_DECREF(reduce);
 | 
				
			||||||
            return res;
 | 
					            return res;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -7396,7 +7387,6 @@ object___reduce_ex___impl(PyObject *self, int protocol)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return _common_reduce(self, protocol);
 | 
					    return _common_reduce(self, protocol);
 | 
				
			||||||
#undef objreduce
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static PyObject *
 | 
					static PyObject *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue