Index: Modules/threadmodule.c =================================================================== --- Modules/threadmodule.c (revision 60075) +++ Modules/threadmodule.c (working copy) @@ -164,7 +164,6 @@ PyObject *key; PyObject *args; PyObject *kw; - PyObject *dict; } localobject; static PyObject * @@ -172,6 +171,7 @@ { localobject *self; PyObject *tdict; + PyObject *localdict; if (type->tp_init == PyBaseObject_Type.tp_init && ((args && PyObject_IsTrue(args)) @@ -189,13 +189,12 @@ self->args = args; Py_XINCREF(kw); self->kw = kw; - self->dict = NULL; /* making sure */ self->key = PyString_FromFormat("thread.local.%p", self); if (self->key == NULL) goto err; - self->dict = PyDict_New(); - if (self->dict == NULL) + localdict = PyDict_New(); + if (localdict == NULL) goto err; tdict = PyThreadState_GetDict(); @@ -205,8 +204,9 @@ goto err; } - if (PyDict_SetItem(tdict, self->key, self->dict) < 0) + if (PyDict_SetItem(tdict, self->key, localdict) < 0) goto err; + Py_DECREF(localdict); return (PyObject *)self; @@ -220,7 +220,6 @@ { Py_VISIT(self->args); Py_VISIT(self->kw); - Py_VISIT(self->dict); return 0; } @@ -230,7 +229,6 @@ Py_CLEAR(self->key); Py_CLEAR(self->args); Py_CLEAR(self->kw); - Py_CLEAR(self->dict); return 0; } @@ -253,6 +251,7 @@ Py_TYPE(self)->tp_free((PyObject*)self); } +/* Return borrowed reference to the local dict */ static PyObject * _ldict(localobject *self) { @@ -278,10 +277,6 @@ return NULL; } - Py_CLEAR(self->dict); - Py_INCREF(ldict); - self->dict = ldict; /* still borrowed */ - if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init && Py_TYPE(self)->tp_init((PyObject*)self, self->args, self->kw) < 0) { @@ -293,11 +288,6 @@ } } - else if (self->dict != ldict) { - Py_CLEAR(self->dict); - Py_INCREF(ldict); - self->dict = ldict; - } return ldict; } @@ -305,25 +295,32 @@ static int local_setattro(localobject *self, PyObject *name, PyObject *v) { - PyObject *ldict; - - ldict = _ldict(self); - if (ldict == NULL) - return -1; + int res = PyObject_GenericSetAttr((PyObject *)self, name, v); - return PyObject_GenericSetAttr((PyObject *)self, name, v); + if (res < 0 && PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyObject *ldict = _ldict(self); + if (ldict == NULL) + return -1; + + PyErr_Clear(); + + res = PyDict_SetItem(ldict, name, v); + } + + return res; } static PyObject * local_getdict(localobject *self, void *closure) { - if (self->dict == NULL) { + PyObject *ldict = _ldict(self); + if (ldict == NULL) { PyErr_SetString(PyExc_AttributeError, "__dict__"); return NULL; } - Py_INCREF(self->dict); - return self->dict; + Py_INCREF(ldict); + return ldict; } static PyGetSetDef local_getset[] = { @@ -369,7 +366,7 @@ /* tp_dict */ 0, /* internal use */ /* tp_descr_get */ 0, /* tp_descr_set */ 0, - /* tp_dictoffset */ offsetof(localobject, dict), + /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ local_new,