加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

当shell终止时,Windows上生成的Ruby进程将死亡

发布时间:2020-12-15 22:58:20 所属栏目:安全 来源:网络整理
导读:我试图在 Windows上使用以下内容生成 Ruby进程: p1 = spawn('ruby','loop.rb',[:out,:err] = ['process.log',"w"],:new_pgroup = true) 然后我也通过以下方式脱离了这个过程: p1.detach 到目前为止,我应该理解创建一个独立于父进程的新进程.我甚至使用new_
我试图在 Windows上使用以下内容生成 Ruby进程:

p1 = spawn('ruby','loop.rb',[:out,:err] => ['process.log',"w"],:new_pgroup => true)

然后我也通过以下方式脱离了这个过程:

p1.detach

到目前为止,我应该理解创建一个独立于父进程的新进程.我甚至使用new_pgroup参数来确保新进程获得自己的进程组.

当我执行我的脚本时,子进程启动并继续运行.产生子进程的脚本的执行也完成了.但是,当我现在关闭shell时,子进程就会死掉.我希望它能继续运行(它在OS X和Linux上运行).我无法弄清楚这是否是Windows上Ruby运行时的错误,或者这是否是Windows的限制以及它如何处理进程.

为了完整性,我想要做的完整Ruby代码:

spawner.rb:可以通过ruby spawner.rb执行,只生成一个新的子进程.进程创建的是loop.rb,这只是一个无限循环.根据操作系统,它为进程组创建指定了不同的参数.

require "tempfile"
require 'rbconfig'

class SpawnTest

  def self.spawn_process

    if os == :windows
      p1 = spawn('ruby',:new_pgroup => true)
    else
      p1 = spawn('ruby',:pgroup => true)
    end

    # Detach from the processes so they will keep running
    puts p1
    Process.detach(p1)
  end

  def self.os
    @os ||= (
    host_os = RbConfig::CONFIG['host_os']
    case host_os
      when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
        :windows
      when /darwin|mac os/
        :macosx
      when /linux/
        :linux
      when /solaris|bsd/
        :unix
      else
        raise Error::WebDriverError,"unknown os: #{host_os.inspect}"
    end
    )
  end
end

if __FILE__ == $0
  SpawnTest.spawn_process
end

loop.rb

$stdout.sync = true
$stderr.sync = true

i = 0
while i < 10000
  $stdout.puts "Iteration #{i}"
  sleep 1
  i = i + 1
end

$stdout.puts "Bye from #{Process.pid}"

我在调查期间找到了win32-process宝石.它似乎是使用win32 API调用生成进程.有谁知道这个库是否能解决这个问题?

任何帮助赞赏.

解决方法

我在Windows中找不到任何进程组的使用,除了将CTRL事件分派给多个进程,如 Process Creation Flags MSDN docs所述:

Process groups are used by the GenerateConsoleCtrlEvent function to enable sending a CTRL+BREAK signal to a group of console processes.

指定CREATE_NEW_PROCESS_GROUP标志时实际发生的是……

…an implicit call to SetConsoleCtrlHandler(NULL,TRUE) is made on behalf of the new process; this means that the new process has CTRL+C disabled. This lets shells handle CTRL+C themselves,and selectively pass that signal on to sub-processes. CTRL+BREAK is not disabled,and may be used to interrupt the process/process group.

From CreateProcess MSDN docs.

请注意,这与使用x按钮关闭控制台窗口不同.在后一种情况下,进程接收CTRL_CLOSE_EVENT,

A signal that the system sends to all processes attached to a console when the user closes the console (either by clicking Close on the console window’s window menu,or by clicking the End Task button command from Task Manager).

From HandlerRoutine callback MSDN docs.

创建进程时,CREATE_NEW_PROCESS_GROUP标志设置的SetConsoleCtrlHandler(NULL,TRUE)不会影响此事件的处理.

以上所有意味着CREATE_NEW_PROCESS_GROUP标志与您正在观察的行为无关.

默认情况下,子进程inherits父控制台窗口和IO句柄.因此,当您通过单击x按钮关闭shell时,它会收到CTRL_CLOSE_EVENT,并且没有不终止的选项.

为避免这种情况,不应将子进程附加到父控制台.这是通过向CreateProcess Windows API提供DETACHED_PROCESS标志来完成的.

By default,a console process inherits its parent’s console

Console processes are not attached to a console if they are created using CreateProcess with DETACHED_PROCESS.

From Creation of a Console MSDN docs.

这就是我认为Ruby的spawn和win32-process gem做的不同.我没有尝试调试两者,以便查看它们提供给CreateProcess的标志的具体差异,尽管这将是一件有趣的事情.

还有其他方法可以在不继承父级的控制台或IO句柄的情况下创建子进程.示例是CREATE_NO_WINDOW或CREATE_NEW_CONSOLE标志,Job Objects等.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读