On sábado, 10 de setembro de 2016 12:31:34 PDT Andrey Semashev wrote:
> On 09/10/16 01:07, Thiago Macieira wrote:
> >> Is there an example in the language where such unwind is required?
> >
> > C++ with POSIX cancellation points implemented by way of forced unwinding.
>
> That's beyond the C++ language.
Indeed. But it's still relevant.
> > Moreover, because std::thread exposes the native handle, it stands to
> > reason that the C++ standard intends for its std::thread class to
> > interoperate cleanly with the underlying threading functions. That means
> > pthread_cancel and pthread_exit must be honoured.
>
> The native handles are left as backdoors for some native APIs that are
> not covered by the standard (yet?) but may still be useful. It doesn't
> automatically make all those APIs compatible with C++, and I don't think
> it intends to. That would be unrealistic.
That's a self-contradicting argument. You can't argue that the handle is
exposed so that people can do things the standard doesn't (yet) describe, then
disallow use of certain API because the standard doesn't describe it.
I maintain that exposing the handle means I should be able to use any function
from the underlying API. If I'm not meant to do it, then the native handle
should be deprecated and removed.
At the very least, it should be QoI and implementation-defined behaviour to use
the underlying API with std::thread. That may make this entire discussion
implementation-specific.
> The only way I see to solve this is to describe the intended behavior in
> the C++ standard, but that requires the behavior to be (a) sane in the
> C++ world and (b) portable beyond POSIX. I wouldn't say that the current
> definition of pthread_cancel or pthread_exit fits (a) - noone wants to
> cancel a thread without running the destructors first.
Agreed.
> Realistically, I don't think pthread_cancel or pthread_exit will get any
> better position in C++. The functions are standardized by POSIX and have
> stable implementations, so it's unlikely they will change in favor of
> C++. At the same time their behavior is incompatible with C++, so I
> don't think it is reasonable to describe them in the standard. Your best
> bet is to propose a C++ alternative. I think the closest thing there is
> now in C++ is thread interruption in Boost.Thread. It comes with a cost,
> and I suspect this was one of the reasons that it didn't get into the
> standard.
There's a very clean way of integrating them. GCC and Glibc have long ago
solved this problem by equating POSIX thread-cancellation points and C++
exceptions. All POSIX thread-cancellation functions are not noexcept, whereas
all others are. Thread cancellation runs C++ local destructors and
pthread_cleanup is implemented in C++ by way of a local variable with
destructor.. This means C++ destructors are run when a cancellation happens
and that POSIX cleanups are run when an exception is thrown. Suddenly, with no
change whatsoever, locker objects like std::lock_guard, std::unique_lock,
QMutexLocker, etc. work just fine and will unlock their objects in case of
cancellation.
I would call this very much compatible with C++. The only difference between a
POSIX thread cancellation and an exception is that you cannot stop the
cancellation. You're allowed to clean up in your catch block, but you must
rethrow.
It's difficult to standardise that because, like you said, POSIX doesn't deal
with C++ and C++ works outside of POSIX. I would actually argue that POSIX
should deal with this, but there may be things C++ could do to make it easier.
Hence this thread.
> >> pthread_cleanup handlers are not required to be implemented in the same
> >> manner as C++ objects. The handlers are not required to be called when
> >> the stack unwinds due to a C++ exception. Similarly, you cannot expect
> >> C++ automatic destructors to be called when you call pthread_exit or
> >> pthread_cancel. Therefore these functions are also off limits in C++.
> >
> > I agree with everything except for the last sentence. Like you and I said,
> > neither standard (C++ or POSIX) describes what happens when you combine
> > the
> > two things together.
>
> Exactly, that's what makes it off limits.
Again, I disagree. Just because there's an interface area that neither
standard dealt with doesn't mean it should never be dealt with. Especially
when there's prior art showing it can be dealt with, cleanly.
Now, this may be in POSIX's camp or it may be entirely up to the
implementation (QoI). Still, the questions I asked bear answering: what does
the group of people most familiar with C++ think the answer should be?