2010-09-20 9 views
5

Estoy escribiendo una extensión C, proporcionando una interfaz entre Ruby y una biblioteca de E/S asincrónica. Al ejecutar las pruebas más de mi código, con frecuencia se producen errores incluyendo (pero no limitados a):¿Cómo evito violaciones de hilos cruzados en una extensión de Ruby?

[BUG] cross-thread violation in rb_thread_schedule() 

asíncrono IO es mi extensión C tendrá que entregar mensajes al rubí desde varios subprocesos (no el hilo principal intérprete) . ¿Cómo evito estas violaciones a la seguridad de las hebras en el proceso?

+0

Ruby 1.8.xo 1.9.x? – llasram

+0

Mi preocupación era 1.8, pero 1.9 es relevante también. –

Respuesta

7

Para ruby ​​1.8.x, la única forma de evitar el error es obvio: solo invoque la API de Ruby/C desde el hilo del intérprete principal. Creo que esto también se aplica a ruby ​​1.9.x, pero no he trabajado con él y no sé cómo su soporte de hilos nativos podría cambiar las cosas. En lugar de tener múltiples hilos nativos que invoquen directamente la API, debe usar el patrón productor/consumidor para entregar las solicitudes desde sus subprocesos nativos secundarios a su código en la cadena principal del intérprete. E idealmente, haga esto sin bloquear innecesariamente otros hilos verdes de Ruby. Si nos fijamos en la implementación de ruby, el programador de hilos de color verde rubí es esencialmente un loop select(). Esto sugiere la siguiente estructura general:

  • Crear una tubería u otro mecanismo de IPC que proporciona una verdadera select() descriptor de archivo -able.
  • Engendre hilos nativos y proporcione el extremo de escritura de la tubería.
  • En el hilo del intérprete principal, introduzca un bucle de evento que llame al rb_thread_wait_fd() en el extremo de lectura del conducto. Esto permitirá que el programador de hilos de color verde rubí ejecute otros hilos verdes.
  • Cuando los subprocesos nativos secundarios tienen solicitudes para el subproceso principal, los ponen en cola y también escriben en el conducto, lo que activa el subproceso verde que ejecuta el bucle de evento.

Ver rb_io_sysread() (aplicación de IO#sysread) por lo que es probable que la limpieza utilizando IO función más simple en la base de código de rubí.

Cuestiones relacionadas