我正在编写一个 C 扩展,提供 Ruby 和异步 I/O 库之间的接口。在我的代码上运行测试时,我经常遇到错误,包括(但不限于):
[BUG] cross-thread violation in rb_thread_schedule()
异步 IO 意味着我的 C 扩展需要从多个线程(而不是主解释器线程)向 ruby 传递消息。在此过程中,如何避免这些线程安全违规?
我正在编写一个 C 扩展,提供 Ruby 和异步 I/O 库之间的接口。在我的代码上运行测试时,我经常遇到错误,包括(但不限于):
[BUG] cross-thread violation in rb_thread_schedule()
异步 IO 意味着我的 C 扩展需要从多个线程(而不是主解释器线程)向 ruby 传递消息。在此过程中,如何避免这些线程安全违规?
对于 ruby 1.8.x,避免错误的唯一方法是显而易见的——只从主解释器线程调用 Ruby/C API。我相信这也适用于 ruby 1.9.x,但我没有使用过它,也不知道它的原生线程支持会如何改变事情。您需要使用生产者/消费者模式将来自辅助本机线程的请求传递到主解释器线程中的代码,而不是让多个本机线程直接调用 API。理想情况下,这样做同时不会不必要地阻塞其他 Ruby 绿色线程。如果您查看 ruby 实现,那么 ruby green 线程调度程序本质上是一个select()
循环。这表明了以下总体结构:
select()
文件描述符的管道或其他 IPC 机制。rb_thread_wait_fd()
在主解释器线程中,输入一个在管道读取端调用的事件循环。这将允许 ruby 绿色线程调度程序运行其他绿色线程。请参阅rb_io_sysread()
(的实现IO#sysread
)了解可能是 ruby 代码库中最简单的干净 IO 使用函数。