Skip to content

Commit 77b83ea

Browse files
committed
Separate coro exception stack
1 parent ef2721d commit 77b83ea

File tree

2 files changed

+34
-26
lines changed

2 files changed

+34
-26
lines changed

Lib/test/test_exceptions.py

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -716,8 +716,6 @@ def print_error():
716716
print_error()
717717
# implicit "del e" here
718718

719-
# TODO: RUSTPYTHON
720-
@unittest.expectedFailure
721719
def test_generator_leaking(self):
722720
# Test that generator exception state doesn't leak into the calling
723721
# frame
@@ -748,8 +746,6 @@ def yield_raise():
748746
del g
749747
self.assertEqual(sys.exc_info()[0], TypeError)
750748

751-
# TODO: RUSTPYTHON
752-
@unittest.expectedFailure
753749
def test_generator_leaking2(self):
754750
# See issue 12475.
755751
def g():
@@ -765,8 +761,6 @@ def g():
765761
pass
766762
self.assertEqual(sys.exc_info(), (None, None, None))
767763

768-
# TODO: RUSTPYTHON
769-
@unittest.expectedFailure
770764
def test_generator_leaking3(self):
771765
# See issue #23353. When gen.throw() is called, the caller's
772766
# exception state should be save and restored.
@@ -786,7 +780,6 @@ def g():
786780
self.assertIs(gen_exc, e)
787781
self.assertEqual(sys.exc_info(), (None, None, None))
788782

789-
@unittest.skip("TODO: RUSTPYTHON")
790783
def test_generator_leaking4(self):
791784
# See issue #23353. When an exception is raised by a generator,
792785
# the caller's exception state should still be restored.
@@ -814,8 +807,6 @@ def g():
814807
# We used to find TypeError here.
815808
self.assertEqual(sys.exc_info(), (None, None, None))
816809

817-
# TODO: RUSTPYTHON
818-
@unittest.expectedFailure
819810
def test_generator_doesnt_retain_old_exc(self):
820811
def g():
821812
self.assertIsInstance(sys.exc_info()[1], RuntimeError)
@@ -828,8 +819,6 @@ def g():
828819
next(it)
829820
self.assertRaises(StopIteration, next, it)
830821

831-
# TODO: RUSTPYTHON
832-
@unittest.expectedFailure
833822
def test_generator_finalizing_and_exc_info(self):
834823
# See #7173
835824
def simple_gen():
@@ -881,8 +870,6 @@ def do_close(g):
881870
g.close()
882871
self._check_generator_cleanup_exc_state(do_close)
883872

884-
# TODO: RUSTPYTHON
885-
@unittest.expectedFailure
886873
def test_generator_del_cleanup_exc_state(self):
887874
def do_del(g):
888875
g = None
@@ -1303,8 +1290,6 @@ def main():
13031290
with self.assertRaises(MainError):
13041291
coro.throw(SubError())
13051292

1306-
# TODO: RUSTPYTHON
1307-
@unittest.expectedFailure
13081293
def test_generator_doesnt_retain_old_exc2(self):
13091294
#Issue 28884#msg282532
13101295
def g():

vm/src/obj/objcoroinner.rs

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ use crate::frame::{ExecutionResult, FrameRef};
44
use crate::pyobject::{PyObjectRef, PyResult};
55
use crate::vm::VirtualMachine;
66

7-
use std::cell::Cell;
7+
use std::cell::{Cell, RefCell};
88

99
#[derive(Debug)]
1010
pub struct Coro {
1111
frame: FrameRef,
1212
closed: Cell<bool>,
1313
running: Cell<bool>,
14+
exceptions: RefCell<Vec<PyBaseExceptionRef>>,
1415
}
1516

1617
impl Coro {
@@ -19,6 +20,7 @@ impl Coro {
1920
frame,
2021
closed: Cell::new(false),
2122
running: Cell::new(false),
23+
exceptions: RefCell::new(vec![]),
2224
}
2325
}
2426

@@ -29,15 +31,32 @@ impl Coro {
2931
}
3032
}
3133

34+
fn run_with_context<F>(&self, func: F, vm: &VirtualMachine) -> PyResult<ExecutionResult>
35+
where
36+
F: FnOnce() -> PyResult<ExecutionResult>,
37+
{
38+
self.running.set(true);
39+
let curr_exception_stack_len = vm.exceptions.borrow().len();
40+
vm.exceptions
41+
.borrow_mut()
42+
.append(&mut self.exceptions.borrow_mut());
43+
let result = func();
44+
self.exceptions.replace(
45+
vm.exceptions
46+
.borrow_mut()
47+
.split_off(curr_exception_stack_len),
48+
);
49+
self.running.set(false);
50+
result
51+
}
52+
3253
pub fn send(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
3354
if self.closed.get() {
3455
return Err(objiter::new_stop_iteration(vm));
3556
}
3657

3758
self.frame.push_value(value.clone());
38-
self.running.set(true);
39-
let result = vm.run_frame(self.frame.clone());
40-
self.running.set(false);
59+
let result = self.run_with_context(|| vm.run_frame(self.frame.clone()), vm);
4160
self.maybe_close(&result);
4261
result?.into_result(vm)
4362
}
@@ -53,9 +72,9 @@ impl Coro {
5372
return Err(exceptions::normalize(exc_type, exc_val, exc_tb, vm)?);
5473
}
5574
vm.frames.borrow_mut().push(self.frame.clone());
75+
let result =
76+
self.run_with_context(|| self.frame.gen_throw(vm, exc_type, exc_val, exc_tb), vm);
5677
self.running.set(true);
57-
let result = self.frame.gen_throw(vm, exc_type, exc_val, exc_tb);
58-
self.running.set(false);
5978
self.maybe_close(&result);
6079
vm.frames.borrow_mut().pop();
6180
result?.into_result(vm)
@@ -67,13 +86,17 @@ impl Coro {
6786
}
6887
vm.frames.borrow_mut().push(self.frame.clone());
6988
self.running.set(true);
70-
let result = self.frame.gen_throw(
89+
let result = self.run_with_context(
90+
|| {
91+
self.frame.gen_throw(
92+
vm,
93+
vm.ctx.exceptions.generator_exit.clone().into_object(),
94+
vm.get_none(),
95+
vm.get_none(),
96+
)
97+
},
7198
vm,
72-
vm.ctx.exceptions.generator_exit.clone().into_object(),
73-
vm.get_none(),
74-
vm.get_none(),
7599
);
76-
self.running.set(false);
77100
vm.frames.borrow_mut().pop();
78101
self.closed.set(true);
79102
match result {

0 commit comments

Comments
 (0)