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.
........
This commit is contained in:
Antoine Pitrou 2010-08-28 18:27:09 +00:00
parent 06509381a8
commit fcd2a7960c
6 changed files with 182 additions and 91 deletions

View file

@ -911,7 +911,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;
@ -971,37 +971,38 @@ 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;
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);
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;
dictoffset += (long)size;
assert(dictoffset > 0);
assert(dictoffset % SIZEOF_VOID_P == 0);
}
Py_DECREF(dict);
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) {
res = f(descr, obj, (PyObject *)Py_TYPE(obj));
@ -1023,8 +1024,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;
@ -1056,27 +1064,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);
@ -1098,6 +1108,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 */