Jnthn answered the question why $*IN.lines blocks in a react block. What isn’t explained is what whenever actually does before it starts blocking.

react { whenever $*IN.lines { .say } }

Looking at the syntax of a whenever block, we see that whenever takes a variable immediatly followed by a block. The only place where a structure like that can be defined is Grammar.nqp.

rule statement_control:sym<whenever> { <sym><.kok> [ || <?{ nqp::getcomp('perl6').language_version eq '6.c' || $*WHENEVER_COUNT >= 0 }> || <.typed_panic('X::Comp::WheneverOutOfScope')> ] { $*WHENEVER_COUNT++ } <xblock($PBLOCK_REQUIRED_TOPIC)> }

Here the grammar just checks a few things without actually generating any code. So we head to Actions.nqp.

method statement_control:sym<whenever>($/) { my $xblock := $<xblock>.ast; make QAST::Op.new( :op<call>, :name<&WHENEVER>, :node($/), $xblock[0], block_closure($xblock[1]) ); }

The whenever block is converted to a call to sub WHENEVER which we find in Supply.pm6.

sub WHENEVER(Supply() $supply, &block) {

There we go. A whenever block takes its first argument of any type and calles .Supply on it, as long as Any is a parent of that type. In the case of $*IN that type will typically be whatever IO::Handle.lines returns.

Seq.new(self!LINES-ITERATOR($close))

To turn a Seq into a Supply Any.Supply calls self.list.Supply . Nowhere in this fairly long chain of method lookups (this can’t be fast) are there any threads to be found. If we want to fix this we need to sneak a Channel into $*IN.lines which does exactly that.

$*IN.^can('lines')[1].wrap(my method { my $channel = Channel.new; start { for callsame() { last if $channel.closed; $channel.send($_) } LEAVE $channel.close unless $channel.closed; } $channel });

Or if we want to be explicit:

use Concurrent::Channelify; react { whenever signal(SIGINT) { say "Got signal"; exit; } whenever $*IN.lines⇒ { say "got line"; } }

We already use ⚛ to indicate atomic operations. Maybe using prefix:<∥> to indicate concurrency makes sense. Anyway, we went lucky once again that Rakudo is implemented (mostly) in Perl 6 so we can find out where we need to poke it whenever we want to change it.