编辑:我想我已经解决了这个问题:https://gist.github.com/niuage/c0637b8dd10549a12b6a223dbd5f158a
我可能一直缺少Process.wait,因此创建了很多僵尸进程。
我有一段大部分时间都在工作的代码,但是一段时间后可能会因为竞争状况而“锁定”自身。
pipe = "goals.png"
(1..100).each do |time|
fork do
# This runs ffmpeg, and gets it to write 1 frame of a video to the pipe 'goals.png'
print "before ffmpeg"
`#{ffmpeg(time, score_crop_options, pipe)}`
exit
end
# Reads from 'pipe'
print "before read"
blob = File.read(pipe)
image = Rocket::Image.from_blob(blob)
# do stuff with image
end
#{ffmpeg(time, pipe)}
写入管道,并一直阻塞,直到从管道读取某些内容为止
File.read(pipe)处于阻塞状态,直到有东西写入到管道中
edit:脚本被锁定时,当我尝试从另一个脚本读取管道时,得到zsh: fork failed: resource temporarily unavailable
。这可能是个好主意...
在大多数情况下,File.read(pipe)
在fork的代码之前执行,因此效果很好,但是过一会儿脚本便停止了:它显示"before ffmpeg"
且从未到达{{1 }} ...
首先,我应该使用线程而不是fork吗?我是否可以控制2条语句(读和写)的运行顺序,以避免出现竞争状况?也许甚至与比赛条件无关,我还缺少一些东西?
答案 0 :(得分:0)
问题不是由竞争状况引起的,而是僵尸进程过多,因为我没有打电话给Process.wait
父进程应该使用Process.wait来收集其子进程的终止状态,或者使用Process.detach来注册对其状态不感兴趣的对象;否则,操作系统可能会累积僵尸进程。
这就是为什么当我尝试从另一个脚本中的管道读取时得到zsh: fork failed: resource temporarily unavailable
的原因。
这是行得通的:
(1..100) do
if fork
# Parent
image = read_image(pipe)
# do stuff with image
Process.wait # I think that's what was missing previously
else
# Child
Open3.popen3(command(time, score_crop_options, pipe)) do |stdin, stdout, stderr, wait_thr|
# stuff
end
exit!(0)
end
end