超时、系统超时&终止符不适用于基于 FFI 的功能
我通过 FFI 为共享库函数(第三方函数)编写了一个包装器。该共享库尝试与服务器建立连接。在连接建立过程中,当服务器无法访问时,第三方功能会等待 3 分钟。为了避免这种情况,在调用 Rails 时我尝试使用以下超时,但不幸的是它不起作用。
- 本机超时
- 系统超时
- 终结器
注意:当我使用终结器时,由它创建的附加进程将变成已失效的进程。
我使用的是 ruby 企业版 1.8
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.
- Native Timeout
- System timeout
- Terminator
Note: when I use Terminator the additional process that is created by it was turning as defunct process.
I am using ruby enterprise version 1.8
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
似乎通过 FFI 的调用完全阻止了 Ruby 的调度程序,不允许任何线程。这可能和Ruby的绿色线程有关。
下面的示例说明了使用 FFI 时 Ruby 并发的行为:
克服此问题的一种方法是分叉一个单独的进程来执行 FFI 调用,并在其上设置超时:
在分叉的子进程中,我们感兴趣的所有内容在做的过程中,监听 INT 信号,如果达到超时,则温和地关闭,当然还有 FFI 调用。
在父进程中,我们只需要让子进程超时,并杀死它,除非它按时完成。
Seems that calls via FFI block Ruby's scheduler completely, not allowing any threading. This may be related to Ruby's green threads.
The below example illustrates how Ruby concurrency behaves when using 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:
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.
更干净一点:
A bit cleaner:
您可以将 C 库中将阻塞的函数标记为“阻塞”函数,FFI 将解锁对这些函数的调用周围的 GIL。 (需要 ffi-1.0.x)。
例如,
@blocking 不是粘性的 - 您需要在每个要标记为阻塞的“attach_function”调用之前设置它。
而且它并不是 100% 可靠的解决方案。中断在本机代码中被阻止的函数将适用于可中断的函数(例如睡眠、读取、写入等),但不适用于某些本机代码(例如CPU 密集型计算,也可能是许多其他类型)。
请注意:在 ruby 1.8.x 上,阻塞函数调用确实很慢(与 1.9 或 JRuby 上的阻塞调用相比)。
You can mark the functions which will block in the C library as 'blocking' functions, and FFI will unlock the GIL around calls to those functions. (Requires ffi-1.0.x).
e.g.
@blocking is not sticky - you need to set it before every 'attach_function' call that you want to mark as blocking.
And its not a 100% sure-fire solution. Interrupting a function which is blocked in native code will work for functions that are interruptible (e.g. sleep, read, write, etc), but won't for some native code (e.g. cpu intensive computations, possibly many other types as well).
Be warned: on ruby 1.8.x, blocking function calls are really slow (compared to blocking calls on 1.9 or JRuby).