Separate coro exception stack

This commit is contained in:
Aviv Palivoda
2020-03-06 10:45:19 +02:00
parent ef2721de8b
commit 77b83ea4f8
2 changed files with 34 additions and 26 deletions

View File

@@ -716,8 +716,6 @@ class ExceptionTests(unittest.TestCase):
print_error()
# implicit "del e" here
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_generator_leaking(self):
# Test that generator exception state doesn't leak into the calling
# frame
@@ -748,8 +746,6 @@ class ExceptionTests(unittest.TestCase):
del g
self.assertEqual(sys.exc_info()[0], TypeError)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_generator_leaking2(self):
# See issue 12475.
def g():
@@ -765,8 +761,6 @@ class ExceptionTests(unittest.TestCase):
pass
self.assertEqual(sys.exc_info(), (None, None, None))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_generator_leaking3(self):
# See issue #23353. When gen.throw() is called, the caller's
# exception state should be save and restored.
@@ -786,7 +780,6 @@ class ExceptionTests(unittest.TestCase):
self.assertIs(gen_exc, e)
self.assertEqual(sys.exc_info(), (None, None, None))
@unittest.skip("TODO: RUSTPYTHON")
def test_generator_leaking4(self):
# See issue #23353. When an exception is raised by a generator,
# the caller's exception state should still be restored.
@@ -814,8 +807,6 @@ class ExceptionTests(unittest.TestCase):
# We used to find TypeError here.
self.assertEqual(sys.exc_info(), (None, None, None))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_generator_doesnt_retain_old_exc(self):
def g():
self.assertIsInstance(sys.exc_info()[1], RuntimeError)
@@ -828,8 +819,6 @@ class ExceptionTests(unittest.TestCase):
next(it)
self.assertRaises(StopIteration, next, it)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_generator_finalizing_and_exc_info(self):
# See #7173
def simple_gen():
@@ -881,8 +870,6 @@ class ExceptionTests(unittest.TestCase):
g.close()
self._check_generator_cleanup_exc_state(do_close)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_generator_del_cleanup_exc_state(self):
def do_del(g):
g = None
@@ -1303,8 +1290,6 @@ class ExceptionTests(unittest.TestCase):
with self.assertRaises(MainError):
coro.throw(SubError())
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_generator_doesnt_retain_old_exc2(self):
#Issue 28884#msg282532
def g():

View File

@@ -4,13 +4,14 @@ use crate::frame::{ExecutionResult, FrameRef};
use crate::pyobject::{PyObjectRef, PyResult};
use crate::vm::VirtualMachine;
use std::cell::Cell;
use std::cell::{Cell, RefCell};
#[derive(Debug)]
pub struct Coro {
frame: FrameRef,
closed: Cell<bool>,
running: Cell<bool>,
exceptions: RefCell<Vec<PyBaseExceptionRef>>,
}
impl Coro {
@@ -19,6 +20,7 @@ impl Coro {
frame,
closed: Cell::new(false),
running: Cell::new(false),
exceptions: RefCell::new(vec![]),
}
}
@@ -29,15 +31,32 @@ impl Coro {
}
}
fn run_with_context<F>(&self, func: F, vm: &VirtualMachine) -> PyResult<ExecutionResult>
where
F: FnOnce() -> PyResult<ExecutionResult>,
{
self.running.set(true);
let curr_exception_stack_len = vm.exceptions.borrow().len();
vm.exceptions
.borrow_mut()
.append(&mut self.exceptions.borrow_mut());
let result = func();
self.exceptions.replace(
vm.exceptions
.borrow_mut()
.split_off(curr_exception_stack_len),
);
self.running.set(false);
result
}
pub fn send(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
if self.closed.get() {
return Err(objiter::new_stop_iteration(vm));
}
self.frame.push_value(value.clone());
self.running.set(true);
let result = vm.run_frame(self.frame.clone());
self.running.set(false);
let result = self.run_with_context(|| vm.run_frame(self.frame.clone()), vm);
self.maybe_close(&result);
result?.into_result(vm)
}
@@ -53,9 +72,9 @@ impl Coro {
return Err(exceptions::normalize(exc_type, exc_val, exc_tb, vm)?);
}
vm.frames.borrow_mut().push(self.frame.clone());
let result =
self.run_with_context(|| self.frame.gen_throw(vm, exc_type, exc_val, exc_tb), vm);
self.running.set(true);
let result = self.frame.gen_throw(vm, exc_type, exc_val, exc_tb);
self.running.set(false);
self.maybe_close(&result);
vm.frames.borrow_mut().pop();
result?.into_result(vm)
@@ -67,13 +86,17 @@ impl Coro {
}
vm.frames.borrow_mut().push(self.frame.clone());
self.running.set(true);
let result = self.frame.gen_throw(
let result = self.run_with_context(
|| {
self.frame.gen_throw(
vm,
vm.ctx.exceptions.generator_exit.clone().into_object(),
vm.get_none(),
vm.get_none(),
)
},
vm,
vm.ctx.exceptions.generator_exit.clone().into_object(),
vm.get_none(),
vm.get_none(),
);
self.running.set(false);
vm.frames.borrow_mut().pop();
self.closed.set(true);
match result {