-
Notifications
You must be signed in to change notification settings - Fork 743
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gsl::finally executes throwing code under noexcept, resulting in runtime crash #1193
Comments
interestingly this has probably been discussed before, e.g.
see |
another implementation enforcing noexcept
|
and a proposal which suggests allowing noexcept(true/false) depending on the provided action:
|
more caveats in research pointing out unsurprisingly there are many interpretations of a scope guard and they can be confusing:
|
https://en.cppreference.com/w/cpp/experimental/scope_success/%7Escope_success
|
Thank you for reporting this issue! This will be discussed at our monthly maintainer's sync. Unfortunately, GSL does not have the power to change the semantics of gsl::finally without the isocpp/CppCoreGuidelines authors modifying the specification. To get a change in GSL we may need to start with an amendment to the guidelines. @gdr-at-ms and I will discuss all of this and update this issue. We appreciate you taking the time to explore alternative implementations for a finally-like machine. We will evaluate these solutions and determine which is best for GSL; then we can work on adopting into the guidelines and implementing in Microsoft/GSL. |
gsl::finally in name, API, and documentation purports to allow arbitrary code to be executed at scope exit, however in practice it executes the provided function within its noexcept(true) destructor which results in a runtime crash if the provided action throws.
In name, there is an implied understanding for gsl::finally, which borrows the "finally" concept from C-based languages, to execute arbitrary, even throwing code. This behavior models what "finally" means in other C-based languages where there isn't a constraint on code in the finally block being non-throwing.
In API, gsl::finally will accept a throwing action without indication/enforcement that the action must not throw even though in practice and at runtime, this is a requirement otherwise the program terminates:
In documentation, it documents that "something gets run", implying any arbitrary code is fine.
In summary, programmers do want a utility to help execute code at scope exit.
First we must decide if we should provide such a utility or if not, and what alternative should exist if any to make code such as:
which would be a reason a programmer would seek out gsl::finally as a utility to execute Update prior to returning without having to manually write it out n-many times.
Next, we must decide if we place exception constraints on gsl::finally.
We may decide to truly allow arbitrary code to execute in gsl::finally, in which case we could specify its destructor's noexcept(false) or based on a template parameter or whether the provided action throws.
If we instead decide to retain gsl::finally's noexcept execution of the action, we should decide how to solve for the problem of:
where we know at compile time such code is invalid and will terminate at runtime. Can we enforce this at compile time? Yes, i.e. by requiring std::is_nothrow_invocable on the function.
Finally, in addition to compile time enforcement, the documentation (and possibly the name) should be updated to make it clear that gsl::finally can only be used with non-throwing code and the user must ensure the supplied action must not throw (else the program will terminate)
The text was updated successfully, but these errors were encountered: