Interrupt causes the following problems because we can't control occurring timing.

Un-safe ensure clause: Generally, ensure clause should not interrupt because it contains important tasks such as freeing resources.

Un-safe resource allocation: If interrupt occurs between resource allocation and assign it to the variable, we can't free this object (however, this problem not too big because we have a gc and appropriate finalizer can free it).

(other problems? please complement me)

I show an example below.

# Example 4
# this method is similar implementation of timeout()
def timeout(sec)
timer_thread = Thread.new(Thread.current){|parent|
sleep(sec)
parent.raise(TimeoutError)
}
begin
yield
ensure
timer_thread.stop # close thread
end
end
timeout(3){
begin
f = # point (a)
open(...) # of course, there are no problem with open(...){|f| ...}
# but it is an example to show the problem
...
ensure
... # point (b)
f.close
end
}

On example 4, there are two problems.

Point (b) is easy to understand. If interrupt was thrown at point (b), then `f.close()' isn't called. It is problem.

On the point (a), it is a position between resource allocation (open()) and assignment `f = '. It is very rare, but it is possible. If we get interrupt before assignment, then we can't free resources (can't call f.close()) in ensure clause. It is also problem.

The problem is we can't control interrupt timing.

= Proposal

Adding interrupt timing control feature to Thread. Introduce two methods to Thread class.

Thread.control_interrupt

Thread.check_interrupt

Rdoc documents are:

Thread.control_interrupt():

call-seq:
Thread.control_interrupt(hash) { ... } -> result of the block

Thread.control_interrupt controls interrupt timing.

interrupt means asynchronous event and corresponding procedure
by Thread#raise, Thread#kill, signal trap (not supported yet)
and main thread termination (if main thread terminates, then all
other thread will be killed).

Eek. Please don't use 'interrupt' word. It makes a lot of confusing to
Unix programmer.

Rdoc documents are:

call-seq:
Thread.control_interrupt(hash) { ... } -> result of the block

Thread.control_interrupt controls interrupt timing.

interrupt means asynchronous event and corresponding procedure
by Thread#raise, Thread#kill, signal trap (not supported yet)
and main thread termination (if main thread terminates, then all
other thread will be killed).

No. control_interrupt should NOT inhibit running trap procedure. Because of,
Thread.control_interrupt() is per-thread, but trap is not per-thread.

btw, Probably it should be per-fiber instead of per-thread.

hash has pairs of ExceptionClass and TimingSymbol. TimingSymbol
is one of them:
- :immediate Invoke interrupt immediately.
- :on_blocking Invoke interrupt while BlockingOperation.

I don't think 'on_blocking' is good name. Example, pthread cancel have
a 'cancellation point' concept and many blocking functions is defined
as cancellation point. but a few non blocking functions also defined
as cancellation point. So, this on_blocking should have a name as
concept likes interruptible point. (but again, i don't like interrupt
word)

Eek. Please don't use 'interrupt' word. It makes a lot of confusing to
Unix programmer.

Okay. Give us a good name.

Rdoc documents are:

call-seq:
Thread.control_interrupt(hash) { ... } -> result of the block

Thread.control_interrupt controls interrupt timing.

interrupt means asynchronous event and corresponding procedure
by Thread#raise, Thread#kill, signal trap (not supported yet)
and main thread termination (if main thread terminates, then all
other thread will be killed).

No. control_interrupt should NOT inhibit running trap procedure. Because of,
Thread.control_interrupt() is per-thread, but trap is not per-thread.

It is not reason. trap handler and an exception from trap handler
interrupt (ah, you don't like this word) ensure clause. It is problem.

Kosaki-san and me talked about it at IRC. Kosaki-san proposed that an
exception from trap handler should be caused as `Thread#raise'. It can
protect from this feature. It seems good. I think mask signal trap
with this feature is more simple.

Any other ideas or comments?

btw, Probably it should be per-fiber instead of per-thread.

Okay.

hash has pairs of ExceptionClass and TimingSymbol. TimingSymbol
is one of them:
- :immediate Invoke interrupt immediately.
- :on_blocking Invoke interrupt while BlockingOperation.

I don't think 'on_blocking' is good name. Example, pthread cancel have
a 'cancellation point' concept and many blocking functions is defined
as cancellation point. but a few non blocking functions also defined
as cancellation point. So, this on_blocking should have a name as
concept likes interruptible point. (but again, i don't like interrupt
word)

Eek. Please don't use 'interrupt' word. It makes a lot of confusing to
Unix programmer.

Okay. Give us a good name.

How's this?

control_interrupt() => defer_async_raise() or defer_unwinding()

"control" is unclear and don't explain what action does. Actually this procedure block provide a defer way.
and "interrupt" is often used for other meanings then I think to avoid it is better.

never => end

"never" seems a word to drop an exception. I like to say "defer to end of block"

below is a rough and draft documentation idea.

a exception is queueed and exception raising will be deferred to an end of control_async_raise block.
a queued exception never be lost.

:on_blocking => raise_point

I prefer to use foo_point rather than "block" because unblocking built-in may allow an exception raise in future.
example, recently we decided to release in zlib even though it doesn't take an IO. I except zlib and other long calculation
method also prefer to allow to raise exceptions.

below is a rough and draft documentation idea.

an exception will be only raised on implicit or explicit on raise point.
almost IO and built-in blockable operation provide implicit raise point
and Thread.may_raise() provide explicit one.

Thread.check_interrupt => Thread.may_raise

"check" is also unclear word to me. and It seems to return boolean value of checking result. I think "check" is what does.
and people want to know what's happen. then I propose may_raise.

"control" is unclear and don't explain what action does. Actually this procedure block provide a defer way.
and "interrupt" is often used for other meanings then I think to avoid it is better.

immediate' does not defer.
I can't accept the namedefer_*'.

never => end

"never" seems a word to drop an exception. I like to say "defer to end of block"

end' is also unclear. how aboutdefer'?

below is a rough and draft documentation idea.

a exception is queueed and exception raising will be deferred to an end of control_async_raise block.
a queued exception never be lost.

:on_blocking => raise_point

I prefer to use foo_point rather than "block" because unblocking built-in may allow an exception raise in future.
example, recently we decided to release in zlib even though it doesn't take an IO. I except zlib and other long calculation
method also prefer to allow to raise exceptions.

below is a rough and draft documentation idea.

an exception will be only raised on implicit or explicit on raise point.
almost IO and built-in blockable operation provide implicit raise point
and Thread.may_raise() provide explicit one.

How about `blockable_point' ?

Thread.check_interrupt => Thread.may_raise

"check" is also unclear word to me. and It seems to return boolean value of checking result. I think "check" is what does.
and people want to know what's happen. then I propose may_raise.

It inspired from CHECK_INTS' from C source code.
I feelmay_raise' is strange.

I prefer not to introduce new methods at all, but instead
overload the existing begin/ensure syntax.

begin async_raise: false
# code in this section will not allow exceptions raised by other threads
...
end
begin
...
ensure async_raise: false
# code in this section will not allow exceptions raised by other threads
...
end

To me, this is not unacceptable. but not fine too. ;-)
Any good name idea is highly welcome.

Eric:
Your syntax overloading looks ok to me. and I think you misunderstand what ko1's Thread.check_interrupt() does.
Current Thread.check_interrupt() doesn't have an argument nor return value. It just behave as pthread_testcancel(),
(i.e. raise an exception if any exception is queueed).
Moreover, I don't like a name of "test_foobar" because it seems to test something and return boolean value.

I prefer not to introduce new methods at all, but instead
overload the existing begin/ensure syntax.

begin async_raise: false
# code in this section will not allow exceptions raised by other threads
...
end
begin
...
ensure async_raise: false
# code in this section will not allow exceptions raised by other threads
...
end

The examples of Thread.may_raise do not guarantee an ensure block will run, because you still have to get to the may_raise call.

It's also going to be error prone because people will forget to turn async exceptions back on again. If you really want to ensure that ensure blocks don't get interrupted asynchronously, just make them that way by default, or provide syntax as Eric suggests.

Honestly, the only safe answer is to disallow asynchronous exceptions. The better long-term design would probably be to provide a built-in messaging/polling mechanism between threads that threads can opt into.

Honestly, the only safe answer is to disallow asynchronous exceptions. The better long-term design would probably be
to provide a built-in messaging/polling mechanism between threads that threads can opt into.

Thread.raise is not big problem, the most big problems are timeout module and Ctrl-C. I don't think we can disallow
ctrl-c.

The key, of course, is to associate a (hidden) queue with each thread
for incoming exceptions from other threads.
This essentially makes Thread#raise analogous to Queue#push

Kosaki,
Was my old post any sort of inspiration for this, or did you
arrive at the same solution independently? You add the ability to
assign different exception delivery policies to each subclass of
Exception.
This seems good on the surface, but won't it complicate the queue
management and make it possible for exceptions to be delivered out of
order? Have you thought about this?

Charlie,
Five years ago, after a bit of arm twisting, you admitted that this
technique could allow thread.raise to be used safely. Why the change of
heart now?

Ah, I want to say "This method checks any defered async interrupts are
there".
It is no ambiguous, I think.

I would suggest:

thread.c: add Thread.exceptions_pending?
This method checks for any deferred exceptions.

"This method returns true if there are exceptions pending"

I don't see why this is a class method. What's wrong with allowing a
thread to check whether another has pending exceptions?

I, too, think that "interrupt" is a term so loaded with hardware
connotations that it should be avoided in this context. Also, async is
sort of redundant, as all exceptions you can defer will be asynchronous
ones.

Do you propose allowing a thread to defer delivery of exceptions to
itself?
What happens if one writes:

Thread.current.raise Exception.new

Can this get deferred, in your new scheme?
Can the delivery of:

Kernel.raise Exception.new

be deferred?

Personally, I think that Thread.current.raise might get deferred, but
Kernel.raise should bypass the queuing mechanism entirely.

OK. I see the logic in using the term "interrupt" if you are actually
trying to unify exceptions from other threads with handling of OS
signals. However, both of these are generally thought of as being
asynchronous events.

If you insist on the async_* prefix, you should apply it consistently.
But, Thread.control_async_interrupt( is getting quite cumbersome, no?

As someone who was writing ISRs for Intel 8080's and Zilog Z-80's in the
late 1970's, here are my suggestions for more conventional vocabulary:

Thread.control_interrupt becomes Thread.interruptible
alternatives would be:
Thread.allow_interrupt or Thread.enable_interrupt
Any of these read better (to a native English speaker).
I like interruptible because it is a property of the thread being
assigned by the construct. After all, nothing actually happens when
this construct is executed. It affects what (might) happen later:

In General:
Code within the block passed to the Thread.interruptible method may
or may not be interrupted according to the specification passed as its
Hash argument.

In the example above, within the block passed to Thread.interruptible,
the thread becomes interruptible by any RuntimeError when/if
it waits for I/O or stops.

=====

The method :async_interrupted? would be better named:
:interrupts_pending?
A thread is not interrupted if it has interrupts being deferred.
The accepted idiom for this is is to say the thread has interrupts
pending for it.

The use case for defining interrupts_pending? method as Thread instance
method is summarized on one word: debugging!

If you have a complex application that has threads which seem to be
unresponsive, you'll want some way to tell whether those threads are
ignoring pending interrupts, or whether they are not even getting
interrupts delivered to them.

I'd also suggest adding another method:

Thread#interrupts_pending #without the question mark

This would return the number of pending interrupts for the thread.
A thread might normally have 0, 1 or 2 pending interrupts. Seeing
dozens pending would indicate a performance problem. This would be
very useful information for debugging and optimization. A thread might
even decide to take some drastic action to if it discovers that it has
too many interrupts pending for itself.

Making Thread.current.raise act like sending exceptions to any other
thread seemed more consistent to me because the method's behavior then
has no special case for Thread.current. I have written low level code
what processed a hardware interrupt, but then decided it must defer it
for later and accomplished this by making the interrupt pending again,
in the controller chip, but masked the interrupt in the CPU. However, I
can see where this might break existing code that currently relies on
Thread.current#raise being exactly synonymous with Kernel#raise
Either behavior is workable.

Charlie,
Five years ago, after a bit of arm twisting, you admitted that this
technique could allow thread.raise to be used safely. Why the change of
heart now?

I had to read through it a bit. Your proposal is quite a bit different
from this one, since it sets threads uninterruptible by default and
you have to opt-in. It would be safe, if you have to opt-in and you
know exactly what that implies (including unsafe interrupting of
ensure blocks). I haven't been following closely, but the proposal on
the current thread is (I believe) intended to designate in Ruby code
uninterruptible blocks of code. That would be safe too, if there's no
change of interrupting between the time you enter an ensure block and
when the uninterruptible section has started.

My bandwidth is limited, so I've been letting this issue go round and
round for a while before I jump in much.

OK. I see the logic in using the term "interrupt" if you are actually
trying to unify exceptions from other threads with handling of OS
signals. However, both of these are generally thought of as being
asynchronous events.

If you insist on the async_* prefix, you should apply it consistently.
But, Thread.control_async_interrupt( is getting quite cumbersome, no?

You are right.

As someone who was writing ISRs for Intel 8080's and Zilog Z-80's in the
late 1970's, here are my suggestions for more conventional vocabulary:

Thread.control_interrupt becomes Thread.interruptible
alternatives would be:
Thread.allow_interrupt or Thread.enable_interrupt
Any of these read better (to a native English speaker).
I like interruptible because it is a property of the thread being
assigned by the construct. After all, nothing actually happens when
this construct is executed. It affects what (might) happen later:

But I feel it is ambiguous that this method returns only current interruptible flags.

How about to use `async_event' ?

In General:
Code within the block passed to the Thread.interruptible method may
or may not be interrupted according to the specification passed as its
Hash argument.

In the example above, within the block passed to Thread.interruptible,
the thread becomes interruptible by any RuntimeError when/if
it waits for I/O or stops.

=====

The method :async_interrupted? would be better named:
:interrupts_pending?
A thread is not interrupted if it has interrupts being deferred.
The accepted idiom for this is is to say the thread has interrupts
pending for it.

As non-native English speaker, I'm not sure the difference with "pending_interrupt?". Yours is good?

The use case for defining interrupts_pending? method as Thread instance
method is summarized on one word: debugging!

It makes sense.

If you have a complex application that has threads which seem to be
unresponsive, you'll want some way to tell whether those threads are
ignoring pending interrupts, or whether they are not even getting
interrupts delivered to them.

I'd also suggest adding another method:

Thread#interrupts_pending #without the question mark

This would return the number of pending interrupts for the thread.
A thread might normally have 0, 1 or 2 pending interrupts. Seeing
dozens pending would indicate a performance problem. This would be
very useful information for debugging and optimization. A thread might
even decide to take some drastic action to if it discovers that it has
too many interrupts pending for itself.

I don't like this method.

I like Thread#interrupts_pending?(err_class) what current Thread#async_interrupt? do.

Number is important? I don't think so.

Making Thread.current.raise act like sending exceptions to any other
thread seemed more consistent to me because the method's behavior then
has no special case for Thread.current. I have written low level code
what processed a hardware interrupt, but then decided it must defer it
for later and accomplished this by making the interrupt pending again,
in the controller chip, but masked the interrupt in the CPU. However, I
can see where this might break existing code that currently relies on
Thread.current#raise being exactly synonymous with Kernel#raise
Either behavior is workable.

Regarding ability of Thread.current.raise to be deferred,
if it works that way now, I'd vote to keep it this way.
Best not to have a special case for Thread.current.raise
If an application requires the special behavior, that's easily achieved:

However, the converse is not easily achieved.
If Thread.current.raise cannot be deferred, the only option would be to
have another thread waiting to rescue the exception and immediately
raise it back to the original thread. Not at all elegant.

I was suggesting "interruptible" as a better alternative for
"async_interrupt_timing" or "control_interrupt". Can either be called
without a block? If so, does it change the way subsequent interrupts
are delivered?

I'd like to avoid the use of "async" because it is an abbreviation for
asynchronous. Ruby core method names tend of avoid abbreviations. That
helps make the language more readable.

In light of all the ways "async_interrupt_timing" method can be used,
perhaps (even better :-) alternative names would be:

My vote is for handle_interrupt or asynchronous_event, but all these
read as idiomatically correct English jargon. I adjusted the values in
the hashes slightly when using a verb phase for the method name to make
the resulting syntax more consistent with English grammar.

The
Thread#pending_interrupt?

method name you propose is also perfectly good English.
Either name is much more descriptive than Thread#async_interrupt?

But, enough syntax. Let's move on to semantics:

It is vital that further interrupts for a thread be deferred immediately
after any asynchronous exception is raised in it. There is no
other way to guarantee that ensure clauses run to completion. This
deferral must happen even when the delivery policy is X=>:immediate !
Charles pointed this out earlier. I just assumed this would be the
case. Can you please confirm?

My five year old proposal incorporated to two similar interrupt deferral
policies to deal with the above issue. One was analogous to your
:immediate, the other was called :always. The :always policy operated
exactly as Ruby does today. No interrupt queues or deferral. It is
intended to provide compatibility with existing Ruby code, however
conceptually flawed.

This new proposal adds the ability to
assign different exception delivery policies to each subclass of
Exception.
This seems good on the surface, but won't it complicate the queue
management and make it possible for exceptions to be delivered out of
order? Have you thought about this?

Have you considered timestamping asynchronous exceptions so the
application can tell how long they had been deferred, and, much more
importantly, sort them to determine the actual order in which they
occurred?

I would suggest that, if you don't want to timestamp exceptions, you
should drop the ability to apply different delivery policies to
different object classes.

Another, less important issue, is having the ability to query the number
of interrupts in the deferral queue. Soft real-time systems may change
their behavior depending on the perceived backlog. But, more
importantly, seeing a large number of deferred interrupts for a thread
is a great debugging aid. Under high loads, a boolean test would not
provide the needed information, as there will usually be one
or two interrupts pending.

I'm ok both handle_interrupt and handle_asynchronous_event.
(and I also agree :defer should go back :never if we accept this name)

My vote is for handle_interrupt or asynchronous_event, but all these
read as idiomatically correct English jargon. I adjusted the values in
the hashes slightly when using a verb phase for the method name to make
the resulting syntax more consistent with English grammar.

The
Thread#pending_interrupt?

method name you propose is also perfectly good English.
Either name is much more descriptive than Thread#async_interrupt?

I'm ok both handle_interrupt and handle_asynchronous_event.
(and I also agree :defer should go back :never if we accept this name)

My vote is for handle_interrupt or asynchronous_event, but all these
read as idiomatically correct English jargon. I adjusted the values in
the hashes slightly when using a verb phase for the method name to make
the resulting syntax more consistent with English grammar.

The
Thread#pending_interrupt?

method name you propose is also perfectly good English.
Either name is much more descriptive than Thread#async_interrupt?