summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2010-08-28 18:27:09 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2010-08-28 18:27:09 (GMT)
commitfcd2a7960c610c149eec66c16e999032457f47eb (patch)
treea25d0ee3bb1ea18a14bd0a86bad54057841f76c1 /Modules
parent06509381a88aa3abb71f70674108fdeb42238606 (diff)
downloadcpython-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.c81
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;