我有一个简单的Haskell程序,可以分解几个进程,每个进程都会休眠一定时间,然后回声。无论我分叉了多少个进程,第二个进程似乎都没有向终端输出任何可见内容。
./scheduler
user@name-of-computer $ 1
3
4
5
产生
$ 1.haskell 4.haskell
3.haskell 5.haskell
如果您使用注释行而不是仅仅打印来运行它,您可以看到
use strict;
use warnings FATAL => 'all';
sub sleep_echo {
my ($second_count) = @_;
my $cpid = fork;
if ($cpid == 0) {
exec "sleep $second_count; echo $second_count";
}
}
for (my $i = 1; $i <= 5; $i++) {
sleep_echo($i);
}
这种行为似乎也特定于Haskell。 Perl没有展出它。
user@name-of-computer $ 1
2
3
4
5
打印
NULL
关于发生了什么的任何想法?
答案 0 :(得分:3)
我已经能够用GHC 7.10.2重现这一点。
Haskell和Perl版本并不完全等效。 Perl版本将创建一个进程后的进程,等待前一个进程启动(未完成)。
Haskell版本将创建多个线程,每个线程启动一个进程。
由于您不等待线程完成启动它们的进程,因此某些线程将因为程序结束太快而失败。 Haskell运行时中的线程执行不是随机的,因此您的程序将(通常)在您的机器上反复出现相同的行为。
您还可以尝试增加进程数以查看发生的情况。有14个进程,第13个进程未启动(在我的配置中)。
如果您删除forkIO
来电,您的程序就可以正常运行:
import System.Process (createProcess, proc, shell, CreateProcess)
import Text.Printf (printf, PrintfArg)
import Control.Monad (void)
sleep :: Integer -> CreateProcess
sleep x = shell (printf "sleep %d; echo %d" x x)
main = foldr1 (>>)
[ void $ createProcess task
| task <- fmap sleep [1..5]
]