fix(exceptions): restore did_throw (#20000)

`!did_throw` doesn't exactly imply `!current_exception`, as `did_throw = false`
is sometimes used to defer exception handling for later (without forgetting the
exception). E.g: uncaught exception handling in `do_cmdline()` may be deferred
to a different call (e.g: when `try_level > 0`).

In #7881, `current_exception = NULL` in `do_cmdline()` is used as an analogue of
`did_throw = false`, but also causes the pending exception to be lost, which
also leaks as `discard_exception()` wasn't used.

It may be possible to fix this by saving/restoring `current_exception`, but
handling all of `did_throw`'s edge cases seems messier. Maybe not worth
diverging over.

This fix also uncovers a `man_spec.lua` bug on Windows: exceptions are thrown
due to Windows missing `man`, but they're lost; skip these tests if `man` isn't
executable.
This commit is contained in:
Sean Dewar
2022-08-30 23:13:52 +01:00
committed by GitHub
parent 6b7eed1884
commit 813476bf72
11 changed files with 143 additions and 111 deletions

View File

@@ -241,9 +241,13 @@ EXTERN int do_profiling INIT(= PROF_NONE); ///< PROF_ values
/// Exception currently being thrown. Used to pass an exception to a different
/// cstack. Also used for discarding an exception before it is caught or made
/// pending.
/// pending. Only valid when did_throw is true.
EXTERN except_T *current_exception;
/// An exception is being thrown. Reset when the exception is caught or as
/// long as it is pending in a finally clause.
EXTERN bool did_throw INIT(= false);
/// Set when a throw that cannot be handled in do_cmdline() must be propagated
/// to the cstack of the previously called do_cmdline().
EXTERN bool need_rethrow INIT(= false);