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