From: Nick Maclaren on
In article <bccee789-1e35-44fd-9c5d-5dec867f20c3(a)t26g2000yqt.googlegroups.com>,
Mathias Gaunard <loufoque(a)gmail.com> wrote:

This is getting ridiculous, so I shall not continue after this.
I have quite a lot of experience on a wide range of systems, including
that of having designed and written several run-time systems that
handled asynchronous exceptions.

> Likewise, you can ignore requests for interruption/termination by
> defining your own handler for SIGINT and SIGTERM.

Er, no. Under many systems, the mere receipt of a signal causes
effects that cannot easily be recovered from.

>> If you don't, think I/O - and, in particular, input from a stream
>> that may be connected to an interactive device or socket. There
>> are lots of other, similar problems.
>
> I don't see any particular problem with that.
> Any expensive operation should be buffered, and you can check if
> you're being requested to cancel at each buffering interval.

The mind boggles. Clearly you have not had much experience with
this.

The most obvious problem is that, under some circumstances, the process
does not get the signal until after the I/O call returns, which is a
major problem when the signal is to say that the process that was going
to send the I/O that is being waited for is now not going to do so!

That is not the only problem, not by a long chalk.

>> A more subtle one is implied by your 'solution'. Should you check
>> before or after the 'wait'?
>
> Seems like you misunderstood.
> The wait does the check automatically. It's one of the necessary
> interruption points provided by the threading support library. It
> couldn't work otherwise, as you'd be stuck waiting with no way to
> cancel the thread...
>
> See the design of Boost.Threads and the former proposed standard
> threads.

I was talking about how you implement such a wait. It is trivial
to specify that there shall be a primitive to do X, but a competent
designer will check that X is feasible first. And, on most systems,
waits are NOT guaranteed to exit cleanly on the receipt of a signal.
Indeed, POSIX explicitly says that does NOT happen for some forms of
wait (e.g. pthread_mutex).

While there are usually paths through the minefield, they are usually
fiendishly complicated, poorly documented, very dependent on the
system's version and configuration and, worst of all, unreliable.


Regards,
Nick Maclaren.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Mathias Gaunard on
On Aug 7, 11:13 am, n...(a)gosset.csi.cam.ac.uk (Nick Maclaren) wrote:
> In article <bccee789-1e35-44fd-9c5d-5dec867f2...(a)t26g2000yqt.googlegroups.com>,
> Mathias Gaunard <loufo...(a)gmail.com> wrote:
>
> This is getting ridiculous, so I shall not continue after this.
> I have quite a lot of experience on a wide range of systems, including
> that of having designed and written several run-time systems that
> handled asynchronous exceptions.

There is no such thing as asynchronous exceptions in standard C++, nor
in C, nor in POSIX.

>
> > Likewise, you can ignore requests for interruption/termination by
> > defining your own handler for SIGINT and SIGTERM.
>
> Er, no. Under many systems, the mere receipt of a signal causes
> effects that cannot easily be recovered from.

Depends on the signal.
SIGKILL and SIGSTOP are not catchable, SIGQUIT, SIGILL, SIGABRT and
SIGFPE are special in that they should never be received unless there
is a bug, the rest is perfectly catchable and ignorable.


> >> If you don't, think I/O - and, in particular, input from a stream
> >> that may be connected to an interactive device or socket. There
> >> are lots of other, similar problems.
>
> > I don't see any particular problem with that.
> > Any expensive operation should be buffered, and you can check if
> > you're being requested to cancel at each buffering interval.
>
> The mind boggles. Clearly you have not had much experience with
> this.

This is how thread cancellation works, even with POSIX threads. Get
over it.
Asynchronous thread cancellation is available as an option with POSIX
threads, but is not recommended at all. You should use cooperative
("deferred") thread cancellation, the default, which mean you may only
get cancelled when you reach a cancellation point.


> The most obvious problem is that, under some circumstances, the process
> does not get the signal until after the I/O call returns, which is a
> major problem when the signal is to say that the process that was going
> to send the I/O that is being waited for is now not going to do so!

If you used asynchronous I/O, you would have less of a problem.
Also, we're not talking about signals here, but global thread-specific
state. You seem to be confusing many things.

A possible solution would be for the blocking call to return when the
thread is requested to interrupt, but that requires integration of
threading and all operating system blocking primitives, and I'm not
aware of any major thread support implementation that does that.


> That is not the only problem, not by a long chalk.

Yet cooperative thread cancellation is the only solution, because just
canceling a thread asynchronously in the middle may leave it in an
arbitrary state.

Killing a thread brutally is even more serious than killing a process
brutally, because the remaining threads can be stuck in a deadlock or
with inconsistent data.

The question, however, is whether thread cancellation is really
necessary, and if the solution is good enough in face of the problems.
It was decided it would not be provided by standard C++ threads.


> I was talking about how you implement such a wait.

If you want to know, look at the implementation of your favourite
POSIX threads library.

pthread_join, pthread_cond_wait, pthread_cond_timedwait,
pthread_testcancel, sem_wait and sigwait are clearly specified to be
cancellation points by POSIX, while other functions are specified not
to be.

Implementations do not seem to have any particular problem with it.


> And, on most systems,
> waits are NOT guaranteed to exit cleanly on the receipt of a signal.

Why are you talking about signals?
I only mentioned signal as an example of termination requests you can
ignore, but they are otherwise quite unrelated to the whole thread
cancellation issue, since it applies to processes, not threads.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Nick Maclaren on
In article <e46dfc3c-aa11-4dd6-83ed-9110018a19c3(a)x25g2000yqj.googlegroups.com>,
Mathias Gaunard <loufoque(a)gmail.com> wrote:
>
>> And, on most systems,
>> waits are NOT guaranteed to exit cleanly on the receipt of a signal.
>
>Why are you talking about signals?
>I only mentioned signal as an example of termination requests you can
>ignore, but they are otherwise quite unrelated to the whole thread
>cancellation issue, since it applies to processes, not threads.

I said that I would not respond, but this seems to be something
about which you are honestly confused.

In the general sense, a signal is ANY way of passing a message from
one entity (say, thread or process) to another. Again in general,
it is the only way that an entity A can tell an entity B to stop
what it is going and do something else.

If entity B is waiting on an event X controlled by an entity C,
there are precisely two ways in which B can wake up:

1) Entity C (and no other) satisfying the condition for event X.

2) An entity (A, C or other) or 'the system' sending some form
of a signal to entity B.

Is that any clearer?


Regards,
Nick Maclaren.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Jonathan Leffler on
On 8/8/10 2:41 PM, Mathias Gaunard wrote:
> On Aug 7, 11:13 am, n...(a)gosset.csi.cam.ac.uk (Nick Maclaren) wrote:
>> In article<bccee789-1e35-44fd-9c5d-5dec867f2...(a)t26g2000yqt.googlegroups.com>,
>> Mathias Gaunard<loufo...(a)gmail.com> wrote:
>>
>> This is getting ridiculous, so I shall not continue after this.
>> I have quite a lot of experience on a wide range of systems, including
>> that of having designed and written several run-time systems that
>> handled asynchronous exceptions.
>
> There is no such thing as asynchronous exceptions in standard C++, nor
> in C, nor in POSIX.
>
>>
>>> Likewise, you can ignore requests for interruption/termination by
>>> defining your own handler for SIGINT and SIGTERM.
>>
>> Er, no. Under many systems, the mere receipt of a signal causes
>> effects that cannot easily be recovered from.
>
> Depends on the signal.
> SIGKILL and SIGSTOP are not catchable, SIGQUIT, SIGILL, SIGABRT and
> SIGFPE are special in that they should never be received unless there
> is a bug, the rest is perfectly catchable and ignorable.

SIGQUIT is generated by the terminal driver on Unix (POSIX) systems in
response to characters typed by the user and can be received when there
is no bug in the program at all (or, perhaps more accurately, there is
no bug that generates SIGQUIT). I don't know of circumstances where the
implementation is allowed to spontaneously generate a SIGQUIT, either.

Jonathan Leffler




--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]