C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Exceptions : lost all hope -- do not resuscitate

From: Giuseppe D'Angelo <giuseppe.dangelo_at_[hidden]>
Date: Sun, 7 Jun 2026 19:26:57 +0200
On 07/06/2026 10:19, Rainer Deyke via Std-Proposals wrote:
>
>
> On 6/7/26 01:58, Sebastian Wittmeier via Std-Proposals wrote:
>> Is this truly UB (anything can go wrong, invalid program according to the standard, not just to the programmer's own rules) or a detected bug?
>
> Disclaimer: I rely on https://cppreference.com/, not the actual text on
> the standard. Quote from https://cppreference.com/:
>
> If lock is called by a thread that already owns the mutex, the behavior
> is undefined: for example, the program may deadlock. An implementation
> that can detect the invalid usage is encouraged to throw a
> std::system_error with error condition resource_deadlock_would_occur
> instead of deadlocking.
>
> This looks unambiguous to me. It is valid for the program to deadlock,
> which is what must happen if the underlying implementation cannot (or
> chooses not to) detect the deadlock. It is valid for the program to
> throw. It is also valid for anything else to happen, because this is
> undefined behavior, not unspecified behavior. It is valid to segfault.
> It is valid to start mining bitcoins. It is valid for the program to
> erase itself from disk. And it is valid for the program to leave itself
> in an inconsistent state and then throw. Technically the entire
> computer could be in an inconsistent state, not just the process.
> Undefined behavior means all bets are off.
>
> In practice, if you're writing non-portable code anyway and you know
> that your specific C++ implementation throws on deadlock while leaving
> the rest of the program in a consistent state, you can take advantage of
> that knowledge. Just be aware that this may not work on any other C++
> implementation. It's analogous to the way POSIX provides a whole bunch
> of non-standard guarantees for C standard library functions that only
> apply to POSIX environments.

I don't think this is entirely accurate. Only re-acquiring a lock from
the *same* thread that already owns it is undefined behavior.

Deadlocking across *different* threads is well-defined behavior. AFAIK,
there's no provision against it; all the deadlocked threads are blocked
in stdlib calls (cf. [intro.progress]), which is a legitimate condition.

An implementation that detects this case, and makes lock() throw the
corresponding exception, is completely conforming. The thrown exception
can be used to gracefully avoid the deadlock (e.g. by having the thread
that was about to deadlock release all its resources, and trying again.
A deadlock requires the thread calling lock() to have >= 1 other lock
acquired.)

In practice, I don't know of any std::mutex implementation that actually
does this. (In some projects I've seen other mutex types featuring
reliable deadlock detection, and this which was actively used by
clients.) I think no-one would disagree with the statement that programs
that deadlock on std::mutex have a bug. I would almost go as far as
classifying this behavior as erroneous -- if it wasn't for the fact that
erroneous behavior allows for termination, which as others have said,
can be a worse outcome than the deadlock.


My 2 c,
--
Giuseppe D'Angelo

Received on 2026-06-07 17:27:06