Subject: Re: [ruby-ffi] New release of FFI gem |
From: Charles Oliver Nutter |
Date: 12/23/10 5:08 PM |
To: ruby-ffi@googlegroups.com |
On Wed, Dec 22, 2010 at 7:15 PM, Evan Phoenix <evan@fallingsnow.net> wrote:
On Dec 22, 2010, at 5:03 PM, Wayne Meissner wrote:
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).I think that this should be simply ignored on 1.8. These is very good precedent for doing so: CAPI methods. Users regularly write methods in C that perform some long action which blocks all threads. Thus users are used to this very thing for a long time and are generally ok with it. If a FFI method blocks the same as a C-API method, then FFI doesn't have a bug.
I tend to agree, with the caveat that if we can maintain the logic to make the calls non-blocking, it might be a nice additional option (in the future). But I don't think this should block getting a 1.8-supporting version of the gem released.
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.Again, I think we can safely ignore this functionality on 1.8 and simply report an error if a user attempts it (which can be detected using the global variable techinque). My reasoning is the same as above, namely that you can't write a C-API method that does this, so there is no need for FFI to support it.
Agreed again. I see FFI as being "C extensions written in Ruby", and when you look at it that way the behaviors don't have to be very different from C exts. Best case might be to just make the calls directly and provide a way for users to opt into pipe/thread or rb_thread_blocking_region-type tricks for specific calls (like maybe via an "attach_blocking_function") or something (and again...this would be a *future* direction...we should get the FFI gem back out there for 1.8 ASAP). - Charlie