Date: Sat, 6 Jun 2026 15:33:44 -0400
I cannot think of an area more likely to instigate lively debate than
exceptions, especially the ones generated by the library.
When I first encountered these I was astounded that a given exception could
be thrown under different conditions. I urge everyone not to repeat or
extend this mistake.
On Sat, Jun 6, 2026, 14:03 Frederick Virchanza Gotham via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> In my work this week, I submitted a pull request containing code like this:
>
> struct S {
> optional<T> var;
> void reset(void) noexcept
> {
> lock_guard mylock{some_global_mutex};
> var.reset();
> }
> }
>
> The pull request went through code review, and a colleague of mine
> responded to say:
>
> "You've marked that function 'noexcept' but 'mutex::lock' might throw"
>
> My response to him was:
>
> "If a mutex fails to lock, the entire process is fried"
>
> Mulling over this for a bit longer, I think that the Standard should
> make a distinction between "normal exceptions" and "lost-all-hope
> exceptions".
>
> For instance if you think a mutex might ever fail to lock in your
> program, I think you should do something like the following:
>
> Step 1 - When the process starts, use 'std::fopen' to open a file on
> disk for writing.
> Step 2 - Invoke 'std::set_terminate_handler' to register a handler
> that writes critical data to disk with 'std::fwrite', then
> 'std::fclose', and then invokes 'std::_Exit' to immediately kill the
> process.
> Step 3 - Mark the aforementioned 'S::reset' method as 'noexcept', and
> just let the terminate handler save critical data if 'mutex::lock'
> throws.
>
> I don't think it's good enough that the Standard simply says that
> 'mutex::lock' might throw 'std::system_error', reason being that this
> isn't something you can just catch and recover from. If a mutex fails
> to lock, you need to do one of the two following:
>
> Strategy 1 - Kill the entire process like I described above (i.e. let
> the terminate handler save critical data and call 'std::_Exit').
>
> Strategy 2 - If not killing the entire process, at least mark a
> portion of the program as unusable -- and this is where I would use a
> "Do not resuscitate" flag (i.e. a DNR flag).
>
> A few years ago when I was programming security cameras in embedded
> Linux, there was a background process that managed the mounting of an
> encrypted volume. Sometimes the encrypted volume would spontaneously
> unmount. We found that if you ever re-mounted the volume after it
> spontaneously unmounted, you would get unreliable behaviour and data
> corruption. For this reason I introduced a 'Do not resuscitate' flag.
> If the encrypted volume were ever to spontaneously unmount, and as
> soon as this was detected, the DNR flag would be set -- meaning that
> the next time a script tried to mount the encrypted volume, the DNR
> flag would forbid its re-mount. This strategy minimised data
> corruption.
>
> I don't think C++ programmers should be accommodating the throwing of
> 'std::system_error' from 'mutex::lock', for example by refraining from
> marking 'S::reset' as 'noexcept'. Instead, C++ should have two
> categories of exception -- normal exceptions and lost-all-hope
> exceptions. So if you were to look up "mutex::lock" on
> 'cppreference.com', instead of it saying:
>
> "Throws std::system_error when errors occur, including errors from the
> underlying operating system that would prevent lock from meeting its
> specifications. The mutex is not locked in the case of any exception
> being thrown."
>
> Perhaps it would say something like:
>
> "Invokes the 'lost_all_hope' terminate handler when errors occur,
> including errors from the underlying operating system that would
> prevent lock from meeting its specifications."
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
exceptions, especially the ones generated by the library.
When I first encountered these I was astounded that a given exception could
be thrown under different conditions. I urge everyone not to repeat or
extend this mistake.
On Sat, Jun 6, 2026, 14:03 Frederick Virchanza Gotham via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> In my work this week, I submitted a pull request containing code like this:
>
> struct S {
> optional<T> var;
> void reset(void) noexcept
> {
> lock_guard mylock{some_global_mutex};
> var.reset();
> }
> }
>
> The pull request went through code review, and a colleague of mine
> responded to say:
>
> "You've marked that function 'noexcept' but 'mutex::lock' might throw"
>
> My response to him was:
>
> "If a mutex fails to lock, the entire process is fried"
>
> Mulling over this for a bit longer, I think that the Standard should
> make a distinction between "normal exceptions" and "lost-all-hope
> exceptions".
>
> For instance if you think a mutex might ever fail to lock in your
> program, I think you should do something like the following:
>
> Step 1 - When the process starts, use 'std::fopen' to open a file on
> disk for writing.
> Step 2 - Invoke 'std::set_terminate_handler' to register a handler
> that writes critical data to disk with 'std::fwrite', then
> 'std::fclose', and then invokes 'std::_Exit' to immediately kill the
> process.
> Step 3 - Mark the aforementioned 'S::reset' method as 'noexcept', and
> just let the terminate handler save critical data if 'mutex::lock'
> throws.
>
> I don't think it's good enough that the Standard simply says that
> 'mutex::lock' might throw 'std::system_error', reason being that this
> isn't something you can just catch and recover from. If a mutex fails
> to lock, you need to do one of the two following:
>
> Strategy 1 - Kill the entire process like I described above (i.e. let
> the terminate handler save critical data and call 'std::_Exit').
>
> Strategy 2 - If not killing the entire process, at least mark a
> portion of the program as unusable -- and this is where I would use a
> "Do not resuscitate" flag (i.e. a DNR flag).
>
> A few years ago when I was programming security cameras in embedded
> Linux, there was a background process that managed the mounting of an
> encrypted volume. Sometimes the encrypted volume would spontaneously
> unmount. We found that if you ever re-mounted the volume after it
> spontaneously unmounted, you would get unreliable behaviour and data
> corruption. For this reason I introduced a 'Do not resuscitate' flag.
> If the encrypted volume were ever to spontaneously unmount, and as
> soon as this was detected, the DNR flag would be set -- meaning that
> the next time a script tried to mount the encrypted volume, the DNR
> flag would forbid its re-mount. This strategy minimised data
> corruption.
>
> I don't think C++ programmers should be accommodating the throwing of
> 'std::system_error' from 'mutex::lock', for example by refraining from
> marking 'S::reset' as 'noexcept'. Instead, C++ should have two
> categories of exception -- normal exceptions and lost-all-hope
> exceptions. So if you were to look up "mutex::lock" on
> 'cppreference.com', instead of it saying:
>
> "Throws std::system_error when errors occur, including errors from the
> underlying operating system that would prevent lock from meeting its
> specifications. The mutex is not locked in the case of any exception
> being thrown."
>
> Perhaps it would say something like:
>
> "Invokes the 'lost_all_hope' terminate handler when errors occur,
> including errors from the underlying operating system that would
> prevent lock from meeting its specifications."
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2026-06-06 19:34:01
