每当signal()以React块顺序依赖时?

时间:2019-05-21 06:29:46

标签: perl6

我有一个小程序,运行直到收到SIGINT或收到来自stdin的两行(按两次Enter键)。反应块逻辑为:

react {
    whenever signal(SIGINT) {
        say "Got signal";
        exit;
    }
    whenever $*IN.lines.Supply {
        say "Got line";
        exit if $++ == 1 ;
    }
}

程序将按预期在输入的两行上退出。

但是CTRL-C不会做任何事情,除非它后面有一行(输入)。

如果我切换了everyever块的顺序,则程序会被SIGINT中断,但是无论何时都不会执行信号

react {
    whenever $*IN.lines.Supply {
        say "Got line";
        exit if $++ == 1 ;
    }
    whenever signal(SIGINT) {
        say "Got signal";
        exit;
    }
}

使用信号接头之前是否还需要其他设置?在反应块中,每当块的顺序重要吗?

更新

因此,似乎lines()调用阻止了React块的执行(感谢@Håkon)。我有点明白。

与读取套接字的类似代码结构相比,我感到困惑。数据的存在(或缺少)对信号处理程序的执行没有影响,在此示例中,它可以读取行数:

my $listener=IO::Socket::Async.listen("0.0.0.0",4432);
react {
    whenever $listener {
        whenever $_.Supply.lines() {
            say "Got line";
        }
    }
    whenever signal(SIGINT) {
        say "Got signal";
        exit;
    }
}

#testing with:
#   curl http://localhost:4432

为什么它的行为与我的原始代码如此不同?

2 个答案:

答案 0 :(得分:8)

顺序不重要只要数据源确实以异步方式运行,不幸的是,这里不是这种情况。 Supply上的Seq强制不引入任何并发性,并立即尝试在Supply上产生要发射的值,这反过来又阻止了从$*IN的读取。因此,第二个订阅没有机会设置;相同的潜在问题会导致观察到的其他问题。

解决方案是强制读取在“其他地方”进行。我们可以使用Supply.from-list(...)来做到这一点,并告诉我们我们确实确实想使用当前的调度程序,而不是其默认的CurrentThreadScheduler。因此,这表现为想要的行为:

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

在将来的Perl 6版本中可能会对该领域进行一些修订。当前的行为意料之中;设计原则是避免遵循隐式引入并发的一般原则,即供应是管理固有存在的并发而不是引入并发的工具。但是,实际上,这里缺乏并发性可能使更多人受益。 (此外,我们可能会考虑提供真正的非阻塞文件I / O,而不是从同步文件I / O +线程构建它。)

答案 1 :(得分:3)

这是一种运行信号处理程序的变体(基于this的答案),但不幸的是$*IN的自动刷新功能似乎已关闭:

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;
    }
}

现在,您必须按CTRL-D来打印行,然后它打印所有以连接字符串形式输入的行,然后关闭$*IN。.如何为{{ 1}}在这种情况下?