summaryrefslogtreecommitdiffstats
path: root/Objects/codeobject.c
diff options
context:
space:
mode:
authorDino Viehland <dinov@microsoft.com>2017-06-13 01:46:35 (GMT)
committerNed Deily <nad@python.org>2017-06-13 01:46:35 (GMT)
commit2997fec01ee7300c6d5940e6c55e4ccf9f56f1b5 (patch)
tree4564d8aaf56739653666c834f29028b918f97173 /Objects/codeobject.c
parentf59cac4b6458e5c47e24a39ba46fb178c3766577 (diff)
downloadcpython-2997fec01ee7300c6d5940e6c55e4ccf9f56f1b5.zip
cpython-2997fec01ee7300c6d5940e6c55e4ccf9f56f1b5.tar.gz
cpython-2997fec01ee7300c6d5940e6c55e4ccf9f56f1b5.tar.bz2
[3.6] bpo-30604: Move co_extra_freefuncs to interpreter state to avoid crashes in threads (#2015)
* Move co_extra_freefuncs to interpreter state to avoid crashes in multi-threaded scenarios involving deletion of code objects * Don't require that extra be zero initialized * Build test list instead of defining empty test class * Ensure extra is always assigned on success * Keep the old fields in the thread state object, just don't use them Add new linked list of code extra objects on a per-interpreter basis so that interpreter state size isn't changed * Rename __PyCodeExtraState_Get and add comment about it going away in 3.7 Fix sort order of import's in test_code.py * Remove an extraneous space * Remove docstrings for comments * Touch up formatting * Fix casing of coextra local * Fix casing of another variable * Prefix PyCodeExtraState with __ to match C API for getting it * Update NEWS file for bpo-30604
Diffstat (limited to 'Objects/codeobject.c')
-rw-r--r--Objects/codeobject.c28
1 files changed, 17 insertions, 11 deletions
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index 22c4f85..d38f185 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -411,11 +411,11 @@ static void
code_dealloc(PyCodeObject *co)
{
if (co->co_extra != NULL) {
- PyThreadState *tstate = PyThreadState_Get();
+ __PyCodeExtraState *state = __PyCodeExtraState_Get();
_PyCodeObjectExtra *co_extra = co->co_extra;
for (Py_ssize_t i = 0; i < co_extra->ce_size; i++) {
- freefunc free_extra = tstate->co_extra_freefuncs[i];
+ freefunc free_extra = state->co_extra_freefuncs[i];
if (free_extra != NULL) {
free_extra(co_extra->ce_extras[i]);
@@ -825,8 +825,6 @@ _PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds)
int
_PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
{
- assert(*extra == NULL);
-
if (!PyCode_Check(code)) {
PyErr_BadInternalCall();
return -1;
@@ -837,6 +835,7 @@ _PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
if (co_extra == NULL || co_extra->ce_size <= index) {
+ *extra = NULL;
return 0;
}
@@ -848,10 +847,10 @@ _PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
int
_PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
{
- PyThreadState *tstate = PyThreadState_Get();
+ __PyCodeExtraState *state = __PyCodeExtraState_Get();
if (!PyCode_Check(code) || index < 0 ||
- index >= tstate->co_extra_user_count) {
+ index >= state->co_extra_user_count) {
PyErr_BadInternalCall();
return -1;
}
@@ -866,13 +865,13 @@ _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
}
co_extra->ce_extras = PyMem_Malloc(
- tstate->co_extra_user_count * sizeof(void*));
+ state->co_extra_user_count * sizeof(void*));
if (co_extra->ce_extras == NULL) {
PyMem_Free(co_extra);
return -1;
}
- co_extra->ce_size = tstate->co_extra_user_count;
+ co_extra->ce_size = state->co_extra_user_count;
for (Py_ssize_t i = 0; i < co_extra->ce_size; i++) {
co_extra->ce_extras[i] = NULL;
@@ -882,20 +881,27 @@ _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
}
else if (co_extra->ce_size <= index) {
void** ce_extras = PyMem_Realloc(
- co_extra->ce_extras, tstate->co_extra_user_count * sizeof(void*));
+ co_extra->ce_extras, state->co_extra_user_count * sizeof(void*));
if (ce_extras == NULL) {
return -1;
}
for (Py_ssize_t i = co_extra->ce_size;
- i < tstate->co_extra_user_count;
+ i < state->co_extra_user_count;
i++) {
ce_extras[i] = NULL;
}
co_extra->ce_extras = ce_extras;
- co_extra->ce_size = tstate->co_extra_user_count;
+ co_extra->ce_size = state->co_extra_user_count;
+ }
+
+ if (co_extra->ce_extras[index] != NULL) {
+ freefunc free = state->co_extra_freefuncs[index];
+ if (free != NULL) {
+ free(co_extra->ce_extras[index]);
+ }
}
co_extra->ce_extras[index] = extra;