Commit bca5f79e authored by Kirill Smelkov's avatar Kirill Smelkov

Fix build for Python 3.7

Starting from Python 3.7 the place to keep exception state was changed:
https://github.com/python/cpython/commit/ae3087c638

NOTE ZEO4 does not wok with Python3.7, because ZEO4 uses "async" for a
variable and that breaks because starting from Python3.7 "async" became
a keyword.

After the fix wendelin.core tests pass under all python2.7, python3.6
and python3.7.
parent 6b5384ae
...@@ -63,6 +63,13 @@ static PyObject *pybuf_str; ...@@ -63,6 +63,13 @@ static PyObject *pybuf_str;
// waiting for numpy to start accept it on python2 // waiting for numpy to start accept it on python2
#define BIGFILE_USE_OLD_BUFFER (PY_VERSION_HEX < 0x03000000) #define BIGFILE_USE_OLD_BUFFER (PY_VERSION_HEX < 0x03000000)
/* whether to use PyThreadState->exc_state,exc_info instead of
* PyThreadState->exc_type & friends.
*
* Starting from Python 3.7 the place to keep exception state was changed:
* https://github.com/python/cpython/commit/ae3087c638 */
#define BIGFILE_USE_PYTS_EXC_INFO (PY_VERSION_HEX >= 0x030700A3)
/* /*
* python representation of VMA - exposes vma memory as python buffer * python representation of VMA - exposes vma memory as python buffer
...@@ -548,8 +555,12 @@ static int pybigfile_loadblk(BigFile *file, blk_t blk, void *buf) ...@@ -548,8 +555,12 @@ static int pybigfile_loadblk(BigFile *file, blk_t blk, void *buf)
PyGILState_STATE gstate; PyGILState_STATE gstate;
PyThreadState *ts; PyThreadState *ts;
PyFrameObject *ts_frame_orig; PyFrameObject *ts_frame_orig;
PyObject *exc_type, *exc_value, *exc_traceback;
PyObject *save_curexc_type, *save_curexc_value, *save_curexc_traceback; PyObject *save_curexc_type, *save_curexc_value, *save_curexc_traceback;
PyObject *save_exc_type, *save_exc_value, *save_exc_traceback; PyObject *save_exc_type, *save_exc_value, *save_exc_traceback;
#if BIGFILE_USE_PYTS_EXC_INFO
_PyErr_StackItem *save_exc_info;
#endif
PyObject *save_async_exc; PyObject *save_async_exc;
// XXX save/restore trash_delete_{nesting,later} ? // XXX save/restore trash_delete_{nesting,later} ?
...@@ -599,9 +610,20 @@ static int pybigfile_loadblk(BigFile *file, blk_t blk, void *buf) ...@@ -599,9 +610,20 @@ static int pybigfile_loadblk(BigFile *file, blk_t blk, void *buf)
XINC( save_curexc_type = set0(&ts->curexc_type) ); XINC( save_curexc_type = set0(&ts->curexc_type) );
XINC( save_curexc_value = set0(&ts->curexc_value) ); XINC( save_curexc_value = set0(&ts->curexc_value) );
XINC( save_curexc_traceback = set0(&ts->curexc_traceback) ); XINC( save_curexc_traceback = set0(&ts->curexc_traceback) );
#if BIGFILE_USE_PYTS_EXC_INFO
XINC( save_exc_type = set0(&ts->exc_state.exc_type) );
XINC( save_exc_value = set0(&ts->exc_state.exc_value) );
XINC( save_exc_traceback = set0(&ts->exc_state.exc_traceback) );
save_exc_info = ts->exc_info;
ts->exc_info = &ts->exc_state;
BUG_ON(ts->exc_state.previous_item != NULL);
#else
XINC( save_exc_type = set0(&ts->exc_type) ); XINC( save_exc_type = set0(&ts->exc_type) );
XINC( save_exc_value = set0(&ts->exc_value) ); XINC( save_exc_value = set0(&ts->exc_value) );
XINC( save_exc_traceback = set0(&ts->exc_traceback) ); XINC( save_exc_traceback = set0(&ts->exc_traceback) );
#endif
XINC( save_async_exc = set0(&ts->async_exc) ); XINC( save_async_exc = set0(&ts->async_exc) );
/* before py3k python also stores exception in sys.exc_* variables (wrt /* before py3k python also stores exception in sys.exc_* variables (wrt
...@@ -802,25 +824,49 @@ out: ...@@ -802,25 +824,49 @@ out:
PyErr_PrintEx(0); PyErr_PrintEx(0);
} }
BUG_ON(ts->curexc_type || ts->curexc_value || ts->curexc_traceback); BUG_ON(ts->curexc_type || ts->curexc_value || ts->curexc_traceback);
if (ts->exc_type) { #if BIGFILE_USE_PYTS_EXC_INFO
if (ts->exc_info != &ts->exc_state) {
WARN("python thread-state found with active generator after loadblk call");
WARN("I will crash"); // TODO dump which generator is still running
BUG();
}
exc_type = ts->exc_state.exc_type;
exc_value = ts->exc_state.exc_value;
exc_traceback = ts->exc_state.exc_traceback;
#else
exc_type = ts->exc_type;
exc_value = ts->exc_value;
exc_traceback = ts->exc_traceback;
#endif
if (exc_type) {
WARN("python thread-state found with handled but not cleared exception state"); WARN("python thread-state found with handled but not cleared exception state");
WARN("I will dump it and then crash"); WARN("I will dump it and then crash");
fprintf(stderr, "ts->exc_type:\t"); PyObject_Print(ts->exc_type, stderr, 0); fprintf(stderr, "ts->exc_type:\t"); PyObject_Print(exc_type, stderr, 0);
fprintf(stderr, "\nts->exc_value:\t"); PyObject_Print(ts->exc_value, stderr, 0); fprintf(stderr, "\nts->exc_value:\t"); PyObject_Print(exc_value, stderr, 0);
fprintf(stderr, "\nts->exc_traceback:\t"); PyObject_Print(ts->exc_traceback, stderr, 0); fprintf(stderr, "\nts->exc_traceback:\t"); PyObject_Print(exc_traceback, stderr, 0);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
PyErr_Display(ts->exc_type, ts->exc_value, ts->exc_traceback); PyErr_Display(exc_type, exc_value, exc_traceback);
} }
BUG_ON(ts->exc_type || ts->exc_value || ts->exc_traceback); BUG_ON(exc_type || exc_value || exc_traceback);
BUG_ON(ts->async_exc); BUG_ON(ts->async_exc);
/* now restore exception state to original */ /* now restore exception state to original */
ts->curexc_type = save_curexc_type; ts->curexc_type = save_curexc_type;
ts->curexc_value = save_curexc_value; ts->curexc_value = save_curexc_value;
ts->curexc_traceback = save_curexc_traceback; ts->curexc_traceback = save_curexc_traceback;
#if BIGFILE_USE_PYTS_EXC_INFO
ts->exc_state.exc_type = save_exc_type;
ts->exc_state.exc_value = save_exc_value;
ts->exc_state.exc_traceback = save_exc_traceback;
ts->exc_info = save_exc_info;
BUG_ON(ts->exc_state.previous_item != NULL);
#else
ts->exc_type = save_exc_type; ts->exc_type = save_exc_type;
ts->exc_value = save_exc_value; ts->exc_value = save_exc_value;
ts->exc_traceback = save_exc_traceback; ts->exc_traceback = save_exc_traceback;
#endif
ts->async_exc = save_async_exc; ts->async_exc = save_async_exc;
Py_XDECREF( save_curexc_type ); Py_XDECREF( save_curexc_type );
...@@ -1178,9 +1224,17 @@ XPyErr_FullClear(void) ...@@ -1178,9 +1224,17 @@ XPyErr_FullClear(void)
x_curexc_type = set0(&ts->curexc_type); x_curexc_type = set0(&ts->curexc_type);
x_curexc_value = set0(&ts->curexc_value); x_curexc_value = set0(&ts->curexc_value);
x_curexc_traceback = set0(&ts->curexc_traceback); x_curexc_traceback = set0(&ts->curexc_traceback);
#if BIGFILE_USE_PYTS_EXC_INFO
/* NOTE clearing top-level exc_state; if there is an active generator
* spawned - its exc state is preserved. */
x_exc_type = set0(&ts->exc_state.exc_type);
x_exc_value = set0(&ts->exc_state.exc_value);
x_exc_traceback = set0(&ts->exc_state.exc_traceback);
#else
x_exc_type = set0(&ts->exc_type); x_exc_type = set0(&ts->exc_type);
x_exc_value = set0(&ts->exc_value); x_exc_value = set0(&ts->exc_value);
x_exc_traceback = set0(&ts->exc_traceback); x_exc_traceback = set0(&ts->exc_traceback);
#endif
x_async_exc = set0(&ts->async_exc); x_async_exc = set0(&ts->async_exc);
Py_XDECREF(x_curexc_type); Py_XDECREF(x_curexc_type);
......
...@@ -275,6 +275,7 @@ setup( ...@@ -275,6 +275,7 @@ setup(
Programming Language :: Python :: 3 Programming Language :: Python :: 3
Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: Implementation :: CPython
Topic :: Software Development :: Libraries :: Python Modules Topic :: Software Development :: Libraries :: Python Modules
Framework :: ZODB\ Framework :: ZODB\
......
# wendelin.core | tox setup # wendelin.core | tox setup
[tox] [tox]
envlist = py27-{ZODB3,ZODB4,ZODB5}-{zblk0,zblk1}-{fs,zeo,neo}-{numpy115,numpy116}, {py35,py36}-{ZODB4,ZODB5}-{zblk0,zblk1}-{fs,zeo}-{numpy115,numpy116} envlist = py27-{ZODB3,ZODB4,ZODB5}-{zblk0,zblk1}-{fs,zeo,neo}-{numpy115,numpy116},
{py35,py36,py37}-{ZODB4,ZODB5}-{zblk0,zblk1}-fs-{numpy115,numpy116},
{py35,py36}-{ZODB4,ZODB5}-{zblk0,zblk1}-zeo-{numpy115,numpy116},
py37-ZODB5-{zblk0,zblk1}-zeo-{numpy115,numpy116}
# (NOTE ZODB3 does not work on python3) # (NOTE ZODB3 does not work on python3)
# (NOTE ZEO4 does not work with python3.7)
# (NOTE NEO does not work on python3 at all) # (NOTE NEO does not work on python3 at all)
# (XXX ZODB5-*-neo are currently failing) # (XXX ZODB5-*-neo are currently failing)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment