问题描述
我已经通过FFI为共享库函数(第三方函数)编写了包装器.该共享库尝试与服务器建立连接.在服务器无法访问的连接建立期间,第三方功能等待3分钟.为了避免在调用rails时出现这种情况,我曾经尝试使用以下超时,但是很遗憾,它没有用.
I have wrote a wrapper through FFI for a shared library function(third party function). This shared library tries to establish a connection with a server. During connection establishment when the server is not reachable third party function waits for 3 mins. In order to avoid that while calling in rails I used tried to use the following timeouts but unfortunately it did not work.
- 本机超时
- 系统超时
- 终结者
注意:当我使用终结者时,由它创建的附加过程被视为已失效的过程.
Note: when I use Terminator the additional process that is created by it was turning as defunct process.
我正在使用ruby企业版1.8
I am using ruby enterprise version 1.8
推荐答案
似乎通过FFI调用完全阻止了Ruby的调度程序,不允许任何线程.这可能与Ruby的绿色线程有关.
Seems that calls via FFI block Ruby's scheduler completely, not allowing any threading. This may be related to Ruby's green threads.
以下示例说明了使用FFI时Ruby并发的行为:
The below example illustrates how Ruby concurrency behaves when using FFI:
require 'ffi'
module Sleep
extend FFI::Library
ffi_lib FFI::Library::LIBC
attach_function :sleep, [:uint], :void
end
thread = Thread.start do
count = 1
while count <= 10
puts count
count += 1
sleep 0.5
end
end
puts "FFI sleep"
Sleep.sleep 5 # Everything blocks, second thread is run after sleep
puts "Ruby sleep"
sleep 5 # Scheduling works, other thread runs simultaneously
thread.join if thread.alive?
克服此问题的一种方法是,分叉一个单独的进程来执行FFI调用,并为此设置超时:
One way to overcome this, is to fork a separate process to carry out the FFI call, and have a timeout on that instead:
require 'ffi'
require 'timeout'
module Sleep
extend FFI::Library
ffi_lib FFI::Library::LIBC
attach_function :sleep, [:uint], :void
end
child_pid = Process.fork do
Signal.trap("INT") do
exit
end
Sleep.sleep 5
exit
end
begin
Timeout::timeout(2) do
Process.wait(child_pid)
end
rescue Timeout::Error
Process.kill("INT", child_pid)
end
在派生子进程中,我们要做的就是监听INT
信号,如果达到超时,该信号会轻轻关闭,当然也要进行FFI调用.
In the forked child process, all we're interested in doing, is listening for the INT
signal to shutdown gently if the timeout is reached, and of course to do the FFI call.
在父进程中,我们只需要使子进程超时并杀死它,除非它按时完成.
In the parent process, we simply need to timeout the child process, and kill it unless it is done on time.
这篇关于超时,系统超时和终结器不适用于基于FFI的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!