gpt4 book ai didi

ruby - 如何在 Ruby 中模仿 execl()

转载 作者:太空宇宙 更新时间:2023-11-04 04:00:28 24 4
gpt4 key购买 nike

我有一个用 C++ 编写的旧应用程序,我正在将其移植到 Ruby。

代码的一部分使用 execl(),以便用其自身的[n更新]副本替换进程,同时维护打开的文件描述符(此应用程序是一项网络服务)。

  if ( execl( "./my-app", "-restart", fd.c_str(), NULL ) < 0 ) {

没过多久就发现 Ruby 没有 execl() 等效项,但您可以使用 Process::spawn:close_others 选项部分伪造它。或者,至少我应该能够根据documentation :

file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not :close_others => true : don't inherit

因此,在我看来,以下内容应该生成一个新进程,该进程可以访问父进程的所有打开文件描述符:

server_fd = @server.to_i
env = {
"APP_REBOOT" => "true",
"APP_SERVER_FD" => server_fd.to_s,
}
command = "ruby my-app.rb"
options = {
:in => :in,
:out => :out,
:err => :err,
:close_others => false,
}
pid = Process.spawn env, command, options
Process.detach pid

这将允许子进程访问描述符...但是我无法弄清楚如何在不关闭所有描述符的情况下退出父进程。换句话说,如果我导致父级在代码末尾退出:

server_fd = @server.to_i
env = {
"APP_REBOOT" => "true",
"APP_SERVER_FD" => server_fd.to_s,
}
command = "ruby my-app.rb"
options = {
:in => :in,
:out => :out,
:err => :err,
:close_others => false,
}
pid = Process.spawn env, command, options
Process.detach pid
exit # ADDED THIS LINE

然后描述符也对子进程关闭。

我感觉这更多是我的流程管理方法的问题,而不是 Ruby 特有的问题,但我不明白我做错了什么。

<小时/>
$ ruby -v
ruby 2.1.0p0 (2013-12-25 revision 44422) [x86_64-linux]
<小时/>

编辑1就在我调用 Process.spawn(或 @mata 指出的 Process.exec)之前,我有一个诊断输出:

system 'lsof -c ruby'

在我的 recover_from_reboot 方法中再次调用该函数。这是重启前输出的尾部,您可以在最后两行看到监听的服务器端口和连接的客户端:

ruby    8957 chris    0u   CHR    136,1      0t0        4 /dev/pts/1
ruby 8957 chris 1u CHR 136,1 0t0 4 /dev/pts/1
ruby 8957 chris 2u CHR 136,1 0t0 4 /dev/pts/1
ruby 8957 chris 3r FIFO 0,8 0t0 12213372 pipe
ruby 8957 chris 4w FIFO 0,8 0t0 12213372 pipe
ruby 8957 chris 5r FIFO 0,8 0t0 12213373 pipe
ruby 8957 chris 6w FIFO 0,8 0t0 12213373 pipe
ruby 8957 chris 7u IPv4 12213374 0t0 TCP localhost.localdomain:boks-servc (LISTEN)
ruby 8957 chris 8u IPv4 12213423 0t0 TCP localhost.localdomain:boks-servc->localhost.localdomain:45249 (ESTABLISHED)

这是我在重新启动后看到的内容:

ruby    8957 chris    3r  FIFO    0,8      0t0 12203947 pipe
ruby 8957 chris 4w FIFO 0,8 0t0 12203947 pipe
ruby 8957 chris 5r FIFO 0,8 0t0 12203948 pipe
ruby 8957 chris 6w FIFO 0,8 0t0 12203948 pipe

这又是我尝试 spawn 还是 exec 的问题。

<小时/>

编辑2根据我的诊断输出,我看到服务器保持绑定(bind)到 fd 7,客户端保持绑定(bind)到 8。通过添加

7 => 7,
8 => 8,

对于我的options数组,我能够使用exec在重新启动时成功地保留这些套接字。我可以手动将服务器和 [client1, client2,...] fd 添加到选项哈希中,但是当 :close_others 应该为我做繁重的工作时,这看起来很脏。

最佳答案

这当然不是我正在寻找的解决方案,但在没有任何有关 :close_options 哈希和 Process.spawnProcess.exec 的情况下,我最终手动将我关心的所有文件描述符添加到 option 数组中,这达到了目的:

server_fd  = self.server.to_i
client_fds = self.clients.map { |c| c.get_fd }
env = {
"APP_REBOOT" => "true",
"APP_SERVER_FD" => server_fd.to_s,
"APP_CLIENT_FDS" => Marshal.dump(client_fds),
}
options = {
:in => :in,
:out => :out,
:err => :err,
:close_others => false,
}
# Add the server socket to the options Hash.
options[server_fd] = server_fd
# Add all the client sockets to the options Hash.
@clients.each { |c| options[c.get_fd] = c.get_fd }
# Begin anew.
Process.exec env, App.binary.to_s, options

我会暂时不接受这个答案,以防有人过来澄清事实。

关于ruby - 如何在 Ruby 中模仿 execl(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23176959/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com