Move exc state to generator. Fixes bpo-25612 (#1773) · python/cpython@ae3087c (original) (raw)

`@@ -16,14 +16,23 @@ static char *NON_INIT_CORO_MSG = "can't send non-None value to a "

`

16

16

`static char *ASYNC_GEN_IGNORED_EXIT_MSG =

`

17

17

`"async generator ignored GeneratorExit";

`

18

18

``

``

19

`+

static inline int

`

``

20

`+

exc_state_traverse(_PyErr_StackItem *exc_state, visitproc visit, void *arg)

`

``

21

`+

{

`

``

22

`+

Py_VISIT(exc_state->exc_type);

`

``

23

`+

Py_VISIT(exc_state->exc_value);

`

``

24

`+

Py_VISIT(exc_state->exc_traceback);

`

``

25

`+

return 0;

`

``

26

`+

}

`

``

27

+

19

28

`static int

`

20

29

`gen_traverse(PyGenObject *gen, visitproc visit, void *arg)

`

21

30

`{

`

22

31

`Py_VISIT((PyObject *)gen->gi_frame);

`

23

32

`Py_VISIT(gen->gi_code);

`

24

33

`Py_VISIT(gen->gi_name);

`

25

34

`Py_VISIT(gen->gi_qualname);

`

26

``

`-

return 0;

`

``

35

`+

return exc_state_traverse(&gen->gi_exc_state, visit, arg);

`

27

36

`}

`

28

37

``

29

38

`void

`

`@@ -87,6 +96,21 @@ _PyGen_Finalize(PyObject *self)

`

87

96

`PyErr_Restore(error_type, error_value, error_traceback);

`

88

97

`}

`

89

98

``

``

99

`+

static inline void

`

``

100

`+

exc_state_clear(_PyErr_StackItem *exc_state)

`

``

101

`+

{

`

``

102

`+

PyObject *t, *v, *tb;

`

``

103

`+

t = exc_state->exc_type;

`

``

104

`+

v = exc_state->exc_value;

`

``

105

`+

tb = exc_state->exc_traceback;

`

``

106

`+

exc_state->exc_type = NULL;

`

``

107

`+

exc_state->exc_value = NULL;

`

``

108

`+

exc_state->exc_traceback = NULL;

`

``

109

`+

Py_XDECREF(t);

`

``

110

`+

Py_XDECREF(v);

`

``

111

`+

Py_XDECREF(tb);

`

``

112

`+

}

`

``

113

+

90

114

`static void

`

91

115

`gen_dealloc(PyGenObject *gen)

`

92

116

`{

`

`@@ -116,6 +140,7 @@ gen_dealloc(PyGenObject *gen)

`

116

140

`Py_CLEAR(gen->gi_code);

`

117

141

`Py_CLEAR(gen->gi_name);

`

118

142

`Py_CLEAR(gen->gi_qualname);

`

``

143

`+

exc_state_clear(&gen->gi_exc_state);

`

119

144

`PyObject_GC_Del(gen);

`

120

145

`}

`

121

146

``

`@@ -187,7 +212,11 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)

`

187

212

`f->f_back = tstate->frame;

`

188

213

``

189

214

`gen->gi_running = 1;

`

``

215

`+

gen->gi_exc_state.previous_item = tstate->exc_info;

`

``

216

`+

tstate->exc_info = &gen->gi_exc_state;

`

190

217

`result = PyEval_EvalFrameEx(f, exc);

`

``

218

`+

tstate->exc_info = gen->gi_exc_state.previous_item;

`

``

219

`+

gen->gi_exc_state.previous_item = NULL;

`

191

220

`gen->gi_running = 0;

`

192

221

``

193

222

`/* Don't keep the reference to f_back any longer than necessary. It

`

`@@ -281,16 +310,7 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)

`

281

310

`if (!result || f->f_stacktop == NULL) {

`

282

311

`/* generator can't be rerun, so release the frame */

`

283

312

`/* first clean reference cycle through stored exception traceback */

`

284

``

`-

PyObject *t, *v, *tb;

`

285

``

`-

t = f->f_exc_type;

`

286

``

`-

v = f->f_exc_value;

`

287

``

`-

tb = f->f_exc_traceback;

`

288

``

`-

f->f_exc_type = NULL;

`

289

``

`-

f->f_exc_value = NULL;

`

290

``

`-

f->f_exc_traceback = NULL;

`

291

``

`-

Py_XDECREF(t);

`

292

``

`-

Py_XDECREF(v);

`

293

``

`-

Py_XDECREF(tb);

`

``

313

`+

exc_state_clear(&gen->gi_exc_state);

`

294

314

`gen->gi_frame->f_gen = NULL;

`

295

315

`gen->gi_frame = NULL;

`

296

316

`Py_DECREF(f);

`

`@@ -810,6 +830,10 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,

`

810

830

`gen->gi_code = (PyObject *)(f->f_code);

`

811

831

`gen->gi_running = 0;

`

812

832

`gen->gi_weakreflist = NULL;

`

``

833

`+

gen->gi_exc_state.exc_type = NULL;

`

``

834

`+

gen->gi_exc_state.exc_value = NULL;

`

``

835

`+

gen->gi_exc_state.exc_traceback = NULL;

`

``

836

`+

gen->gi_exc_state.previous_item = NULL;

`

813

837

`if (name != NULL)

`

814

838

`gen->gi_name = name;

`

815

839

`else

`