Skip to content

Commit 192b6a3

Browse files
committed
Put a critical section around bytecodes that access gi_frame_state
1 parent ccc65c6 commit 192b6a3

File tree

5 files changed

+95
-37
lines changed

5 files changed

+95
-37
lines changed

Include/internal/pycore_opcode_metadata.h

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/bytecodes.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,22 +1135,24 @@ dummy_func(
11351135
PyObject *retval_o;
11361136
assert(frame != &entry_frame);
11371137
if ((tstate->interp->eval_frame == NULL) &&
1138-
(Py_TYPE(receiver_o) == &PyGen_Type || Py_TYPE(receiver_o) == &PyCoro_Type) &&
1139-
((PyGenObject *)receiver_o)->gi_frame_state < FRAME_EXECUTING)
1138+
(Py_TYPE(receiver_o) == &PyGen_Type ||
1139+
Py_TYPE(receiver_o) == &PyCoro_Type))
11401140
{
11411141
_PyInterpreterFrame *gen_frame;
11421142
PyGenObject *gen = (PyGenObject *)receiver_o;
11431143
Py_BEGIN_CRITICAL_SECTION(gen);
1144-
gen_frame = &gen->gi_iframe;
1145-
STACK_SHRINK(1);
1146-
_PyFrame_StackPush(gen_frame, v);
1147-
gen->gi_frame_state = FRAME_EXECUTING;
1148-
gen->gi_exc_state.previous_item = tstate->exc_info;
1149-
tstate->exc_info = &gen->gi_exc_state;
1150-
assert(INSTRUCTION_SIZE + oparg <= UINT16_MAX);
1151-
frame->return_offset = (uint16_t)(INSTRUCTION_SIZE + oparg);
1152-
assert(gen_frame->previous == NULL);
1153-
gen_frame->previous = frame;
1144+
if (gen->gi_frame_state < FRAME_EXECUTING) {
1145+
gen_frame = &gen->gi_iframe;
1146+
STACK_SHRINK(1);
1147+
_PyFrame_StackPush(gen_frame, v);
1148+
gen->gi_frame_state = FRAME_EXECUTING;
1149+
gen->gi_exc_state.previous_item = tstate->exc_info;
1150+
tstate->exc_info = &gen->gi_exc_state;
1151+
assert(INSTRUCTION_SIZE + oparg <= UINT16_MAX);
1152+
frame->return_offset = (uint16_t)(INSTRUCTION_SIZE + oparg);
1153+
assert(gen_frame->previous == NULL);
1154+
gen_frame->previous = frame;
1155+
}
11541156
Py_END_CRITICAL_SECTION();
11551157
DISPATCH_INLINED(gen_frame);
11561158
}
@@ -1185,6 +1187,7 @@ dummy_func(
11851187

11861188
op(_SEND_GEN_FRAME, (receiver, v -- receiver, gen_frame: _PyInterpreterFrame *)) {
11871189
PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver);
1190+
Py_BEGIN_CRITICAL_SECTION(gen);
11881191
DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type);
11891192
DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING);
11901193
STAT_INC(SEND, hit);
@@ -1197,6 +1200,7 @@ dummy_func(
11971200
assert(INSTRUCTION_SIZE + oparg <= UINT16_MAX);
11981201
frame->return_offset = (uint16_t)(INSTRUCTION_SIZE + oparg);
11991202
gen_frame->previous = frame;
1203+
Py_END_CRITICAL_SECTION();
12001204
}
12011205

12021206
macro(SEND_GEN) =
@@ -1214,6 +1218,7 @@ dummy_func(
12141218
#endif
12151219
frame->instr_ptr++;
12161220
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
1221+
Py_BEGIN_CRITICAL_SECTION(gen);
12171222
assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
12181223
assert(oparg == 0 || oparg == 1);
12191224
gen->gi_frame_state = FRAME_SUSPENDED + oparg;
@@ -1239,6 +1244,7 @@ dummy_func(
12391244
RELOAD_STACK();
12401245
LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
12411246
value = temp;
1247+
Py_END_CRITICAL_SECTION();
12421248
LLTRACE_RESUME_FRAME();
12431249
}
12441250

@@ -3136,6 +3142,7 @@ dummy_func(
31363142

31373143
op(_FOR_ITER_GEN_FRAME, (iter -- iter, gen_frame: _PyInterpreterFrame*)) {
31383144
PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter);
3145+
Py_BEGIN_CRITICAL_SECTION(gen);
31393146
DEOPT_IF(Py_TYPE(gen) != &PyGen_Type);
31403147
DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING);
31413148
STAT_INC(FOR_ITER, hit);
@@ -3145,6 +3152,7 @@ dummy_func(
31453152
gen->gi_exc_state.previous_item = tstate->exc_info;
31463153
tstate->exc_info = &gen->gi_exc_state;
31473154
gen_frame->previous = frame;
3155+
Py_END_CRITICAL_SECTION();
31483156
// oparg is the return offset from the next instruction.
31493157
frame->return_offset = (uint16_t)(INSTRUCTION_SIZE + oparg);
31503158
}

Python/executor_cases.c.h

Lines changed: 21 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 48 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)