Subject: Re: [ruby-ffi] New release of FFI gem |
From: Wayne Meissner |
Date: 12/22/10 7:03 PM |
To: ruby-ffi@googlegroups.com |
On 23 December 2010 05:16, Charles Oliver Nutter <headius@headius.com> wrote:
Wayne: Can you summarize what's needed to get 1.8.7 support back in the gem?
It should (ffi master) build and install on 1.8.x. The main reason I dropped support for everything but 1.9.2+ on MacOS, was to reduce the surface area of the things I had to support, to actually get a new release out the door. I figured that anyone who cared about the other versions+platforms that broke would help to fix them. This happened with win32 support (thanks to Luis & Jon), which is why it got fixed almost immediately ... but its only been this week that people have started to make noise about 1.8.x not working. There are a couple of different problems in 1.8.x 1) Blocking calls. These are C functions which will wait (e.g. on I/O). Calling one of these will lock up the interpreter until the function returns. The only way I've found to fix this for 1.8 is to: a) create a pipe b) spin up a new native thread, pass it the converted native arguments and the write end of the pipe c) have the ruby thread go to sleep until the pipe becomes readable via rb_thread_wait_fd() d) once the native thread returns from the function call, write to the pipe e) ruby thread wakes up from rb_thread_wait_fd(), closes the pipe, joins on the native thread Not exactly rocket surgery, but not trivial either - and there will need to be two implementations, one for pthreads, one for win32 (assuming we can't get just settle for 1.9.2+ on win32). 2) Callbacks from non-ruby threads. This is possibly more complicated, and there does not appear (unless I missed it) a way in 1.8.x to detect attempts to call into the interpreter from a non-ruby thread. This manifests as non-obvious crashes, that look to be in completely different sections of code. I think there is a simple way to detect non-ruby threads calling back, just by storing/clearing the current thread id in a global var when entering/exiting native code, and checking that from the callback code. This would mean the callback just does not get called when called from a non-ruby thread (and possibly an error is logged). Fixing it properly so callbacks from non-ruby threads actually work, will be something similar to what is done for 1.9.x, but with the twist of using a pipe instead of a mutex+condvar.