简单的例子,它不适用于我的平台(Ruby 2.2,Cygwin):
#!/usr/bin/ruby
backtt = fork { exec('mintty','/usr/bin/zsh','-i') }
Process.detach(backtt)
exit
Run Code Online (Sandbox Code Playgroud)
这个小程序(从shell启动时)应该跨越一个终端窗口(mintty),然后让我回到shell提示符.
然而,虽然它创建了薄荷窗口,但之后我没有shell提示符,并且我无法在调用shell中键入任何内容.
但是当我在分离之前引入一个小延迟时,要么使用'sleep',要么在stdout上打印一些内容,它会按预期工作:
#!/usr/bin/ruby
backtt = fork { exec('mintty','/usr/bin/zsh','-i') }
sleep 1
Process.detach(backtt)
exit
Run Code Online (Sandbox Code Playgroud)
为什么这有必要?
顺便说一下,我很清楚我可以(从外壳)做一个
mintty /usr/bin/zsh -i &
Run Code Online (Sandbox Code Playgroud)
直接,或者我可以...... &从Ruby内部使用system(),但这不是重点.我特别感兴趣的fork/exec/detach是Ruby 中的行为.任何见解?
发布作为答案,因为评论太长了
虽然我不是Ruby的专家,根本不了解Cygwin,但这种情况对我来说非常熟悉,来自C/C++.
此脚本太短,因此父级的父级完成,而孙级尝试启动.
如果您在分离后和退出前进行睡眠会发生什么?
如果我的理论是正确的,它也应该有效.您的程序在任何(或足够的)线程切换发生之前退出.
我把这些问题称为"中断的手抖动".虽然这是心理学术语,但它描述了会发生什么.
睡眠"放弃时间片",导致线程切换,
控制台输出(任何文件I/O)运行到信号量,也导致线程切换.
如果我的想法是正确的,它也应该工作,如果你不"睡觉",只计数到1e9(取决于计算的速度),因为然后抢占式多任务使得甚至线程切换本身也不会放弃CPU.
所以这是编程中的一个错误(恕我直言:在这种情况下竞争条件是哲学的),但很难找到"谁"负责.涉及很多事情.
根据文档:
\n\n\n\n\n\n
Process::detach通过设置一个单独的 Ruby 线程来防止这种情况,该线程的唯一工作是在进程终止时获取进程 pid 的状态。
注意:我不能在任何可用的操作系统上重现此行为,并且我将其发布为答案只是为了格式化。
\n\n由于Process.detach(backtt)透明地创建了一个线程,我建议您尝试:
#!/usr/bin/ruby\nbacktt = fork { exec(\'mintty\',\'/usr/bin/zsh\',\'-i\') }\n# \xe2\x87\x93\xe2\x87\x93\xe2\x87\x93\xe2\x87\x93\xe2\x87\x93\nProcess.detach(backtt).join\nexit\nRun Code Online (Sandbox Code Playgroud)\n\n这无论如何都不是黑客行为(与愚蠢相反sleep),因为您可能知道底层命令应该或多或少立即返回。我不是 cygwin 的专家,但它可能对线程有一些特定的问题,所以,让这个线程被处理。
| 归档时间: |
|
| 查看次数: |
874 次 |
| 最近记录: |