- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个用 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.spawn
或 Process.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/
假设我 putenv 一个环境变量 ABC,然后执行 execl,或者我执行 execle 并将 ABC 添加到 envp 数组中我传递给 execle 的指针。 如果有的话,有区别吗? 最佳答案 p
我试图在 C++ 中运行 execl(),但它失败了,我不确定原因。 string fileName = "test.txt"; string computerName = "jssoile@
POSIX 系统公开了一系列 exec 函数,这些函数允许将可能不同的东西加载到当前进程中,保持打开的文件描述符、进程标识符等。 这可以出于多种原因完成,在我的例子中,这是自举——我想更改我自己进程的
我正在使用 c 中的 find 命令进行编程,但当我想对文件使用 exec 时,我被阻止了。 如果它是一个目录,那么很简单,我只使用 chdir(path) 但在文件上我有错误不是目录,所以我不能在上
if (fork_return==0) { printf("FROM THE CHILD PROCESS \n"); //print process id printf("The chil
我真的很喜欢这方面的一些调试帮助。我从早上到凌晨 4 点就一直在做这件事。 (我预计会在 7 小时内交付此内容 [上午 11 点]) main.c 中的所有内容都有效,但是当我创建一些子进程来使用 e
我试图理解这个系统调用(execle()),但我不知道它是如何工作的。我不知道如何使用 char* envp[],我们必须将其作为参数传递。我已经尝试过,但它不起作用: #include #incl
我有一个程序可以读取文件,对其进行处理并将结果放入输出文件中。当我有一个参数(输入文件)时,我创建输出文件并写入内容。 我创建了一个 fork() 以便将 stdout 重定向为 write() 内容
#include #include #include #define MAXLINE 512 main(int argc,char* argv[]){ int k; for (k
程序从配置文件中读取一些值,有些已定义,有些未定义,有些值为 0,有些处于事件状态。 我有以下代码: char *arg1="", *arg1_value="", *arg2="", *arg
你能帮我解决这个问题吗?execl 调用的程序“exam”和“students”执行了多少次?我认为正确的答案是程序“考试”有 8 个运行时间,“学生”有 0 个运行时间,因为在前两个 fork 中将
我正在制作一个 C 程序,该程序使用 execl 来执行 ls 命令来列出文件。如果在没有任何命令行参数的情况下调用程序,则会列出当前目录,如果用户将文件目录指定为命令行参数,则会列出该目录。 exe
我使用 TCC 编译并运行了以下程序在 Windows 7 下出现应用程序崩溃: #include int main(void) { if (execlp("c:\\windows\\sys
我正在使用 cywin 在 Windows 上编译 crashme 源代码,我遇到了一些编译错误。 错误: crashme.c: In function 'vfork_main': crashme.c
在UNIX环境下的系统编程上下文中,在使用C++编程语言时,在我的理解中,execl()会传入它要运行的程序的路径,以及一个vector。当传入该 vector 时,我将其理解为传入入口点,通常是 m
我有以下两个简单的程序: bye.cc #include int main() { std::cout #include #include #include using namespace
这个 execl 语句可能有什么问题?当我尝试运行它时,接收可执行文件提示 argc 小于 3。当我打印 argv 内容时,我得到以下信息: argv[1] = -1076146944 argv[2]
我的目标是学习如何执行 execle() 函数。我在 Head First C 书中找到了这段代码。 这是主进程代码(diner_info.c): #include #include int ma
在一个项目上工作,当我调用 execl() 时它不工作。它在 fork 之后调用,应该重新执行当前文件。(参数在文件的前面声明): argument = argv[0]; int err =execl
我正在尝试用 C 语言重现此命令: ls | wc > output.txt 因此,为此,我编写了以下程序: #include #include #include #include #incl
我是一名优秀的程序员,十分优秀!