On Sat, 29 May 2021 01:42:19 -0700 (PDT)
Öö Tiib <
oot...@hot.ee> wrote:
> On Friday, 28 May 2021 at 14:02:11 UTC+3, Chris Vine wrote:
> > With linux's NPTL as implemented by
> > glibc this occurs by the emission of a "pseudo-exception" which you can
> > catch with a catch-all but which (if you do catch it) you must rethrow
> > in your catch block - in other words, you cannot stop cancellation by
> > using a catch block once it has started but you can do clean-up.
>
> Does that pseudo exception not cause std::terminate when thrown from
> noexcept function? Does it mean that implementing noexcept functions
> by catching and handling everything is impossible?
If a function is cancellable, then with the glibc implementation (NPTL)
it cannot be noexcept. I don't know about other cancellation
implementations which unwind the stack. It is up to the programmer to
determine whether the function is to be cancellable or is to be
noexcept: if the function contains a POSIX cancellation point (or
applies a function containing a POSIX cancellation point), the
programmer can either allow or disallow cancellation during the
execution of the function.
Of course, the same is true if you use flags and exceptions to emulate
cancellation.
> > The point about thread cancellation using deferred cancellation is that
> > nearly all the POSIX functions which can block in the kernel, including
> > blocking reads and condition variable waits, are specified as
> > cancellation points in the SUS, so any such blocking in the kernel will
> > be awoken by a cancellation request (assuming cancellation is not
> > blocked at that particular point in the code). You cannot emulate that
> > in POSIX with flags and exeptions except by having a signal generate
> > EINTR so as to force the kernel wait in question to end in order to
> > check the flag, which has a number of undesirable effects of its own for
> > multi-threaded programs. Furthermore some POSIX blocking functions
> > (including pthread_cond_wait) are specified as not interruptible by
> > EINTR.
>
> What are the scenarios where there are no opportunities to check
> the flags? The blocking functions I've used on posix have timeouts
> or versions with timeouts, nonblocking options (O_NONBLOCK) or
> do wake up spuriously frequently enough. But it is sure possible
> that I've missed scenario as there have been only dozen or so
> posix projects.
The base case is a thread waiting for something to happen which it
turns out can no longer happen in the manner required. There are
numerous variations on this of course.
If the blocking function in question has a timeout option then yes you
could use timeouts and loop on the timeout to check a flag and throw an
exception if the flag is set. If the function in question does not
have a timeout option but has a EAGAIN option (say you have a file
descriptor set O_NONBLOCK), polling a flag in a loop is possible but
usually sub-optimal because you have to mitigate an otherwise tight loop
by use of sched_yield(), pthread_yield(), usleep() or similar in the
loop - and using usleep() is problematic because if the waiting event
occurs, you introduce variable latency into its handling. (Obviously if
you have a non-blocking file descriptor and you are selecting on the
descriptor the issue is different, but then you are not looking at
thread cancellation: instead your business is to remove the descriptor
from the selection set.) For blocking functions which return on an
interrupt (not all do), using EINTR via pthread_kill is a possibility
but then the signal in question cannot be one of a set on which
sigwait() is waiting and you cannot set SA_RESTART for it. Relying on
asynchronous signals and EINTR, and throwing an exception if a quit
flag is set, is just a poor version of what cancellation does better in
my view.
Thread cancellation is not something you need often. But when you need
it, you need it, either by emulating it in some way or employing it
directly.
> > On a unix-like OS, there is really no problem with thread cancellation
> > apart from a lack of familiarity arising from the fact it does not
> > feature in the C++ standard and is not usuably available on the windows
> > platform.
>
> Testing of magical, non-mockable features is really no problem?
> I can't find programmers that do no defects so we need to test.
Testing anything to do with the interaction of different threads with
one another is difficult, including any scheme to emulate cancellation
of one thread by another in the way you have mentioned. Thread
cancellation, if properly done, turns out to be another synchronization
exercise.