我已經通過FFI爲共享庫函數(第三方函數)編寫了一個包裝。該共享庫嘗試與服務器建立連接。在服務器不可達的連接建立期間,第三方功能等待3分鐘。爲了避免在使用rails時調用,我試圖使用下面的超時,但不幸的是它沒有工作。超時,系統超時&終止符不能用於基於FFI的功能
- 本地超時
- 系統超時
- 終結者
注:當我使用終結者由它車削解散過程中創建的額外過程。
我使用紅寶石企業版1.8
我已經通過FFI爲共享庫函數(第三方函數)編寫了一個包裝。該共享庫嘗試與服務器建立連接。在服務器不可達的連接建立期間,第三方功能等待3分鐘。爲了避免在使用rails時調用,我試圖使用下面的超時,但不幸的是它沒有工作。超時,系統超時&終止符不能用於基於FFI的功能
注:當我使用終結者由它車削解散過程中創建的額外過程。
我使用紅寶石企業版1.8
似乎通過FFI塊紅寶石的調度程序調用完全,不允許任何線程。這可能與Ruby的綠色線程有關。
下面的例子示出的Ruby併發的行爲使用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呼叫,並且對那個代替超時:
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電話。
在父進程中,我們只需要超時子進程,並殺死它,除非它按時完成。
您可以標記將阻塞在C庫中的函數作爲「阻塞」函數,並且FFI將在調用這些函數時解鎖GIL。 (需要ffi-1.0.x)。
例如
require 'ffi'
module Sleep
extend FFI::Library
ffi_lib FFI::Library::LIBC
# Tell FFI that this function may block
@blocking = true
attach_function :sleep, [:uint], :void
end
@blocking不黏膩 - 你需要每一個「attach_function」叫,你要標記爲阻塞之前設置它。
而且它不是100%肯定的解決方案。中斷在本地代碼中被阻塞的函數將適用於可中斷的函數(例如睡眠,讀取,寫入等),但不適用於某些本地代碼(例如cpu密集型計算,可能還有許多其他類型)。
被警告:在ruby 1.8.x上,阻止函數調用是真的是慢(與阻止1.9或JRuby上的調用相比)。
的位清潔器:
require 'ffi'
module Sleep
extend FFI::Library
ffi_lib FFI::Library::LIBC
attach_function :sleep, [:uint], :void, :blocking => true
end
是有一個FFI交替或有一個變通來克服這個問題。 –
使用解決方法更新了我的答案。 – gnab
解決方法奏效,但它創建了很多不存在的流程。在這段時間內,它使我的服務器不可用。 –