| Index: Modules/threadmodule.c |
| =================================================================== |
| --- Modules/threadmodule.c (revision 66142) |
| +++ 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,11 @@ |
| goto err; |
| } |
| - if (PyDict_SetItem(tdict, self->key, self->dict) < 0) |
| + if (PyDict_SetItem(tdict, self->key, localdict) < 0) { |
| + Py_DECREF(localdict); |
| goto err; |
| + } |
| + Py_DECREF(localdict); |
| return (PyObject *)self; |
| @@ -220,7 +222,6 @@ |
| { |
| Py_VISIT(self->args); |
| Py_VISIT(self->kw); |
| - Py_VISIT(self->dict); |
| return 0; |
| } |
| @@ -230,7 +231,6 @@ |
| Py_CLEAR(self->key); |
| Py_CLEAR(self->args); |
| Py_CLEAR(self->kw); |
| - Py_CLEAR(self->dict); |
| return 0; |
| } |
| @@ -253,6 +253,7 @@ |
| Py_TYPE(self)->tp_free((PyObject*)self); |
| } |
| +/* Return borrowed reference to the local dict */ |
| static PyObject * |
| _ldict(localobject *self) |
| { |
| @@ -278,10 +279,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) { |
| @@ -294,39 +291,39 @@ |
| } |
| - /* The call to tp_init above may have caused another thread to run. |
| - Install our ldict again. */ |
| - if (self->dict != ldict) { |
| - Py_CLEAR(self->dict); |
| - Py_INCREF(ldict); |
| - self->dict = ldict; |
| - } |
| - |
| return ldict; |
| } |
| static int |
| local_setattro(localobject *self, PyObject *name, PyObject *v) |
| { |
| - PyObject *ldict; |
| - |
| - ldict = _ldict(self); |
| + PyObject *ldict = _ldict(self); |
| if (ldict == NULL) |
| return -1; |
| - return PyObject_GenericSetAttr((PyObject *)self, name, v); |
| + if (v != NULL) { |
| + return PyDict_SetItem(ldict, name, v); |
| + } else { |
| + int res; |
| + res = PyDict_DelItem(ldict, name); |
| + if ((res < 0) && PyErr_ExceptionMatches(PyExc_KeyError)) { |
| + PyErr_SetObject(PyExc_AttributeError, name); |
| + } |
| + 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[] = { |
| @@ -372,7 +369,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, |
| @@ -389,10 +386,6 @@ |
| if (ldict == NULL) |
| return NULL; |
| - if (Py_TYPE(self) != &localtype) |
| - /* use generic lookup for subtypes */ |
| - return PyObject_GenericGetAttr((PyObject *)self, name); |
| - |
| /* Optimization: just look in dict ourselves */ |
| value = PyDict_GetItem(ldict, name); |
| if (value == NULL) |