Throwing callback leads to program terminations in absl::Cleanup
- Dominant language
- C++
- Stars
- 18.1k
- Forks
- 3.2k
- Avg merge
- 20h 36m
- Merged PRs (30d)
- 1
Description
**Describe the bug**
Let `Callback` be a type, whose `operator()` is `noexcept(false)` and actually throws.
When an object of such a type is passed as the callback for `absl::Cleanup`, then the destructor `~Cleanup` will always abort the program at runtime, because it is (implicitly) `noexcept`.
I would expect one of the following two possibilities:
- The program doesn't compile, because `Cleanup` `static_assert`s that the callback type is `nothrow_invocable`.
- The destructor propagates the exception (this would require marking it `noexcept(std::is_nothrow_invocable_v)`.
**Steps to reproduce the bug**
Consider the following minimal example:
```
#include
int main() {
try {
absl::Cleanup cl{[]() {throw 42;}};
} catch(...) {}
}
```
[Link to godbolt](https://godbolt.org/z/9cz1K4fTf)
**What system are you using**
I am using Ubuntu 22.04 and G++ 11.1, but the behavior should be the same on
any standard-conforming compiler and platform.
**Additional context**
I am aware that "throwing destructors" are a somewhat controversial topic. Maybe a compromise would be, to `static_assert` as a default, but to provide a possibility to opt out of that assertion, e.g.:
```
absl::Cleanup cl{[]() noexcept {}}; // Fine
absl::Cleanup cl2{[]() {throw 42;}}; // Assertion failure, not noexcept
absl::Cleanup cl3{[]() {throw 42;}}; // Fine
```
I am willing to provide an implementation as soon as we have discussed, what the desired behavior should be.
A problem might be, that the "safer" suggestions (involving the `static_assert`) are a breaking change for callback types that do not throw, but are not explicitly marked `noexcept`.
Best regards
Johannes
Contributor guide
Assessment
This issue has not been assessed yet.