简单的例子,在我的平台上不起作用(
Ruby 2.2,Cygwin):
#!/usr/bin/ruby backtt = fork { exec('mintty','/usr/bin/zsh','-i') } Process.detach(backtt) exit
这个小程序(当从shell启动时)应该跨越一个终端窗口(mintty),然后让我回到shell提示符.
但是,在创建mintty窗口时,我之后没有shell提示,并且我无法在调用shell中键入任何内容.
但是,当我在分离之前引入一个小的延迟,要么使用“睡眠”,或者通过在stdout上打印某些东西,它的工作原理如下:
#!/usr/bin/ruby backtt = fork { exec('mintty','-i') } sleep 1 Process.detach(backtt) exit
为什么这是必要的?
BTW,我很清楚,我可以(从外壳)做一个
mintty /usr/bin/zsh -i &
直接或者我可以从Ruby里面使用系统(……&),但这不是这里的一点.我对Ruby中的fork / exec / detach行为感兴趣.任何见解?
解决方法
张贴作为答案,因为它是太长的评论
虽然我不是Ruby的专家,根本不知道Cygwin,但是这种情况听起来很熟悉,来自C/C++.
这个脚本太短,所以父级的父级完成,而孙子尝试开始.
如果您在分离后退出睡眠,会发生什么情况?
如果我的理论是正确的,它也应该是正常的.在任何(或足够的)线程切换发生之前,您的程序退出.
我称这种问题“手抖”.虽然这是心理术语,但它描述了发生了什么.
睡眠“放弃时间片”,导致线程切换,
控制台输出(任何文件I / O)都会进入信号量,也导致线程切换.
如果我的想法是正确的,它也应该工作,如果你不“睡觉”,只要计算1e9(取决于计算速度),因为那么抢先的多任务使得线程切换本身不会放弃cpu.
所以编程中的错误(IMHO:种族条件在这种情况下是哲学的),但是很难找到“谁”是负责任的.有很多事情涉及.