mirror of
https://github.com/python/cpython.git
synced 2025-12-18 06:41:40 +00:00
[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
This commit is contained in:
parent
f59cac4b64
commit
2997fec01e
6 changed files with 180 additions and 23 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue