summaryrefslogtreecommitdiffstats
path: root/Objects/object.c
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2010-08-28 18:17:03 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2010-08-28 18:17:03 (GMT)
commit1a9a9d543327397396827642895410183f8902d5 (patch)
tree56ded308662fe5b0a410edef287cb23133ccc574 /Objects/object.c
parent64a38c0eb5b7fd6e4ee5f3e912cff9eda8dd19af (diff)
downloadcpython-1a9a9d543327397396827642895410183f8902d5.zip
cpython-1a9a9d543327397396827642895410183f8902d5.tar.gz
cpython-1a9a9d543327397396827642895410183f8902d5.tar.bz2
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 'Objects/object.c')
-rw-r--r--Objects/object.c113
1 files changed, 65 insertions, 48 deletions
diff --git a/Objects/object.c b/Objects/object.c
index ef23ac1..3bde659 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -954,7 +954,7 @@ _PyObject_NextNotImplemented(PyObject *self)
/* Generic GetAttr functions - put these in your tp_[gs]etattro slot */
PyObject *
-PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
+_PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
{
PyTypeObject *tp = Py_TYPE(obj);
PyObject *descr = NULL;
@@ -990,36 +990,37 @@ PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
}
}
- /* Inline _PyObject_GetDictPtr */
- dictoffset = tp->tp_dictoffset;
- if (dictoffset != 0) {
- PyObject *dict;
- if (dictoffset < 0) {
- Py_ssize_t tsize;
- size_t size;
-
- tsize = ((PyVarObject *)obj)->ob_size;
- if (tsize < 0)
- tsize = -tsize;
- size = _PyObject_VAR_SIZE(tp, tsize);
-
- dictoffset += (long)size;
- assert(dictoffset > 0);
- assert(dictoffset % SIZEOF_VOID_P == 0);
- }
- dictptr = (PyObject **) ((char *)obj + dictoffset);
- dict = *dictptr;
- if (dict != NULL) {
- Py_INCREF(dict);
- res = PyDict_GetItem(dict, name);
- if (res != NULL) {
- Py_INCREF(res);
- Py_XDECREF(descr);
- Py_DECREF(dict);
- goto done;
+ if (dict == NULL) {
+ /* Inline _PyObject_GetDictPtr */
+ dictoffset = tp->tp_dictoffset;
+ if (dictoffset != 0) {
+ if (dictoffset < 0) {
+ Py_ssize_t tsize;
+ size_t size;
+
+ tsize = ((PyVarObject *)obj)->ob_size;
+ if (tsize < 0)
+ tsize = -tsize;
+ size = _PyObject_VAR_SIZE(tp, tsize);
+
+ dictoffset += (long)size;
+ assert(dictoffset > 0);
+ assert(dictoffset % SIZEOF_VOID_P == 0);
}
+ dictptr = (PyObject **) ((char *)obj + dictoffset);
+ dict = *dictptr;
+ }
+ }
+ if (dict != NULL) {
+ Py_INCREF(dict);
+ res = PyDict_GetItem(dict, name);
+ if (res != NULL) {
+ Py_INCREF(res);
+ Py_XDECREF(descr);
Py_DECREF(dict);
+ goto done;
}
+ Py_DECREF(dict);
}
if (f != NULL) {
@@ -1042,8 +1043,15 @@ PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
return res;
}
+PyObject *
+PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
+{
+ return _PyObject_GenericGetAttrWithDict(obj, name, NULL);
+}
+
int
-PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
+_PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
+ PyObject *value, PyObject *dict)
{
PyTypeObject *tp = Py_TYPE(obj);
PyObject *descr;
@@ -1075,27 +1083,29 @@ PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
}
}
- dictptr = _PyObject_GetDictPtr(obj);
- if (dictptr != NULL) {
- PyObject *dict = *dictptr;
- if (dict == NULL && value != NULL) {
- dict = PyDict_New();
- if (dict == NULL)
- goto done;
- *dictptr = dict;
- }
- if (dict != NULL) {
- Py_INCREF(dict);
- if (value == NULL)
- res = PyDict_DelItem(dict, name);
- else
- res = PyDict_SetItem(dict, name, value);
- if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
- PyErr_SetObject(PyExc_AttributeError, name);
- Py_DECREF(dict);
- goto done;
+ if (dict == NULL) {
+ dictptr = _PyObject_GetDictPtr(obj);
+ if (dictptr != NULL) {
+ dict = *dictptr;
+ if (dict == NULL && value != NULL) {
+ dict = PyDict_New();
+ if (dict == NULL)
+ goto done;
+ *dictptr = dict;
+ }
}
}
+ if (dict != NULL) {
+ Py_INCREF(dict);
+ if (value == NULL)
+ res = PyDict_DelItem(dict, name);
+ else
+ res = PyDict_SetItem(dict, name, value);
+ if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
+ PyErr_SetObject(PyExc_AttributeError, name);
+ Py_DECREF(dict);
+ goto done;
+ }
if (f != NULL) {
res = f(descr, obj, value);
@@ -1117,6 +1127,13 @@ PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
return res;
}
+int
+PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
+{
+ return _PyObject_GenericSetAttrWithDict(obj, name, value, NULL);
+}
+
+
/* Test a value used as condition, e.g., in a for or if statement.
Return -1 if an error occurred */