is whenever signal() in react block order dependent?

The order doesn't matter provided the data sources really behave in an asynchronous manner, which unfortunately is not the case here. The Supply coercer on a Seq does not introduce any concurrency, and does immediately try to produce a value to emit on the Supply, which in turn blocks on reading from $*IN. Thus, the second subscription doesn't have chance to be set up; the same underlying issue causes the other problems observed.

The solution is to force the reading to happen "elsewhere". We can do that with Supply.from-list(...), plus telling it we really do want to use the current scheduler rather than its default CurrentThreadScheduler. Thus, this behaves as wanted:

react {
    whenever Supply.from-list($*IN.lines, scheduler => $*SCHEDULER) {
        say "Got line";
        exit if $++ == 1 ;
    }
    whenever signal(SIGINT) {
        say "Got signal";
        exit;
    }
}

It's likely this area will be revised somewhat in future Perl 6 versions. The current behavior was well-intended; the design principle was to avoid implicit introduction of concurrency, following the general principle that supplies are a tool for managing concurrency that inherently exists, rather than for introducing it. However, in reality, the lack of concurrency here has probably tripped up more folks than it has helped. (Further, we may look into offering real non-blocking file I/O, rather than building it from sync file I/O + threads.)


Here is a variant that runs the signal handler (based on this answer), but unfortunately autoflushing of $*IN seems to be turned off:

my $lines = supply {
    whenever start $*IN.lines.Supply {
        whenever .lines { .emit }
    }
}.Channel;

react {
    whenever signal(SIGINT) {
        say "Got signal";
        exit;
    }
    whenever $lines {
        say "Got line: '{$_}'";
        exit if $++ == 1;
    }
}

Now you have to press CTRL-D to print the lines, and then it print all lines entered as a concatenated string and after that $*IN is closed.. How can I turn on autoflushing for $*IN in this case?

Tags:

Raku