diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2010-08-28 18:27:09 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2010-08-28 18:27:09 (GMT) |
commit | fcd2a7960c610c149eec66c16e999032457f47eb (patch) | |
tree | a25d0ee3bb1ea18a14bd0a86bad54057841f76c1 /Modules | |
parent | 06509381a88aa3abb71f70674108fdeb42238606 (diff) | |
download | cpython-fcd2a7960c610c149eec66c16e999032457f47eb.zip cpython-fcd2a7960c610c149eec66c16e999032457f47eb.tar.gz cpython-fcd2a7960c610c149eec66c16e999032457f47eb.tar.bz2 |
Merged revisions 84344 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k
........
r84344 | antoine.pitrou | 2010-08-28 20:17:03 +0200 (sam., 28 août 2010) | 4 lines
Issue #1868: Eliminate subtle timing issues in thread-local objects by
getting rid of the cached copy of thread-local attribute dictionary.
........
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_threadmodule.c | 81 |
1 files changed, 38 insertions, 43 deletions
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index ad55f6d..c37dc20 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -13,6 +13,7 @@ #include "pythread.h" static PyObject *ThreadError; +static PyObject *str_dict; /* Lock objects */ @@ -259,8 +260,6 @@ typedef struct { PyObject *key; PyObject *args; PyObject *kw; - /* The current thread's local dict (necessary for tp_dictoffset) */ - PyObject *dict; PyObject *weakreflist; /* List of weak references to self */ /* A {localdummy weakref -> localdict} dict */ PyObject *dummies; @@ -272,9 +271,9 @@ typedef struct { static PyObject *_ldict(localobject *self); static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref); -/* Create and register the dummy for the current thread, as well as the - corresponding local dict */ -static int +/* Create and register the dummy for the current thread. + Returns a borrowed reference of the corresponding local dict */ +static PyObject * _local_create_dummy(localobject *self) { PyObject *tdict, *ldict = NULL, *wr = NULL; @@ -310,15 +309,14 @@ _local_create_dummy(localobject *self) goto err; Py_CLEAR(dummy); - Py_CLEAR(self->dict); - self->dict = ldict; - return 0; + Py_DECREF(ldict); + return ldict; err: Py_XDECREF(ldict); Py_XDECREF(wr); Py_XDECREF(dummy); - return -1; + return NULL; } static PyObject * @@ -364,7 +362,7 @@ local_new(PyTypeObject *type, PyObject *args, PyObject *kw) if (self->wr_callback == NULL) goto err; - if (_local_create_dummy(self) < 0) + if (_local_create_dummy(self) == NULL) goto err; return (PyObject *)self; @@ -380,7 +378,6 @@ local_traverse(localobject *self, visitproc visit, void *arg) Py_VISIT(self->args); Py_VISIT(self->kw); Py_VISIT(self->dummies); - Py_VISIT(self->dict); return 0; } @@ -391,7 +388,6 @@ local_clear(localobject *self) Py_CLEAR(self->args); Py_CLEAR(self->kw); Py_CLEAR(self->dummies); - Py_CLEAR(self->dict); Py_CLEAR(self->wr_callback); /* Remove all strong references to dummies from the thread states */ if (self->key @@ -437,9 +433,9 @@ _ldict(localobject *self) dummy = PyDict_GetItem(tdict, self->key); if (dummy == NULL) { - if (_local_create_dummy(self) < 0) + ldict = _local_create_dummy(self); + if (ldict == NULL) return NULL; - ldict = self->dict; if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init && Py_TYPE(self)->tp_init((PyObject*)self, @@ -456,14 +452,6 @@ _ldict(localobject *self) ldict = ((localdummyobject *) dummy)->localdict; } - /* The call to tp_init above may have caused another thread to run. - Install our ldict again. */ - if (self->dict != ldict) { - Py_INCREF(ldict); - Py_CLEAR(self->dict); - self->dict = ldict; - } - return ldict; } @@ -471,29 +459,25 @@ static int local_setattro(localobject *self, PyObject *name, PyObject *v) { PyObject *ldict; + int r; ldict = _ldict(self); if (ldict == NULL) return -1; - return PyObject_GenericSetAttr((PyObject *)self, name, v); -} + r = PyObject_RichCompareBool(name, str_dict, Py_EQ); + if (r == 1) { + PyErr_Format(PyExc_AttributeError, + "'%.50s' object attribute '%U' is read-only", + Py_TYPE(self)->tp_name, name); + return -1; + } + if (r == -1) + return -1; -static PyObject * -local_getdict(localobject *self, void *closure) -{ - PyObject *ldict; - ldict = _ldict(self); - Py_XINCREF(ldict); - return ldict; + return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict); } -static PyGetSetDef local_getset[] = { - {"__dict__", (getter)local_getdict, (setter)NULL, - "Local-data dictionary", NULL}, - {NULL} /* Sentinel */ -}; - static PyObject *local_getattro(localobject *, PyObject *); static PyTypeObject localtype = { @@ -527,12 +511,12 @@ static PyTypeObject localtype = { /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, - /* tp_getset */ local_getset, + /* tp_getset */ 0, /* tp_base */ 0, /* 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, @@ -544,20 +528,29 @@ static PyObject * local_getattro(localobject *self, PyObject *name) { PyObject *ldict, *value; + int r; ldict = _ldict(self); if (ldict == NULL) return NULL; + r = PyObject_RichCompareBool(name, str_dict, Py_EQ); + if (r == 1) { + Py_INCREF(ldict); + return ldict; + } + if (r == -1) + return NULL; + if (Py_TYPE(self) != &localtype) /* use generic lookup for subtypes */ - return PyObject_GenericGetAttr((PyObject *)self, name); + return _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict); /* Optimization: just look in dict ourselves */ value = PyDict_GetItem(ldict, name); if (value == NULL) /* Fall back on generic to get __class__ and __dict__ */ - return PyObject_GenericGetAttr((PyObject *)self, name); + return _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict); Py_INCREF(value); return value; @@ -582,8 +575,6 @@ _localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref) PyObject *ldict; ldict = PyDict_GetItem(self->dummies, dummyweakref); if (ldict != NULL) { - if (ldict == self->dict) - Py_CLEAR(self->dict); PyDict_DelItem(self->dummies, dummyweakref); } if (PyErr_Occurred()) @@ -931,6 +922,10 @@ PyInit__thread(void) if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0) return NULL; + str_dict = PyUnicode_InternFromString("__dict__"); + if (str_dict == NULL) + return NULL; + /* Initialize the C thread library */ PyThread_init_thread(); return m; |