diff options
author | Dino Viehland <dinov@microsoft.com> | 2017-06-13 01:46:35 (GMT) |
---|---|---|
committer | Ned Deily <nad@python.org> | 2017-06-13 01:46:35 (GMT) |
commit | 2997fec01ee7300c6d5940e6c55e4ccf9f56f1b5 (patch) | |
tree | 4564d8aaf56739653666c834f29028b918f97173 /Objects/codeobject.c | |
parent | f59cac4b6458e5c47e24a39ba46fb178c3766577 (diff) | |
download | cpython-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.c | 28 |
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; |