From: Charles Oliver Nutter Date: 2009-08-03T22:06:51+09:00 Subject: Re: JRuby, ffi, bad file descriptor Ahhh. Yeah I see the problem. In JRuby, because we don't normally have access to the "real" file descriptor for any IO channel, all our logic for fileno is basically fake. We keep an artificial list of numbers that map to IO channels and use that as our file descriptor table. In this case, you're pulling in a real file descriptor from the system, which does not exist in our table, so we raise an error. In order for us to support arbitrary descriptors in our IO we'd probably need an implementation of IO that used all low-level C APIs rather than Java IO APIs. There's currently no (public) way to get from a file descriptor to an IO channel in Java APIs. So I'll divert this issue by asking: what does this get you that our built-in tempfile support does not? We do not use MRI's tempfile.rb; we've implemented our own on top of Java's tempfile support that performs quite a bit better. Perhaps there's a missing feature we can add. It would also be worth discussing this with Wayne Meissner. It would certainly be *nice* if we could transparently support real file descriptors, and he may know a way to do it. On Mon, Aug 3, 2009 at 7:21 AM, Daniel Berger wrote: > On Aug 2, 10:34 pm, Charles Oliver Nutter wrote: >> Got the source of that temp.rb handy? It looks like it's passing a >> bad/closed descriptor to IO.new or something... > > require 'ffi' > > class FileTemp < File >   extend FFI::Library > >   attach_function 'fileno',  [:pointer], :int >   attach_function 'fclose',  [:pointer], :int >   attach_function 'mkstemp', [:string],  :int >   attach_function 'tmpfile', [],         :pointer >   attach_function 'tmpnam',  [:string],  :string >   attach_function 'umask',   [:int],     :int > >   TMPDIR = ENV['TEMP'] || ENV['TMP'] || '/tmp' > >   def initialize(delete = true, template = 'rb_file_temp_XXXXXX') >      @fptr = nil > >      if delete >         @fptr = tmpfile() >         fd = fileno(@fptr) >      else >         begin >            omask = umask(077) >            fd = mkstemp(template) >            raise SystemCallError, 'mkstemp()' if fd < 0 >         ensure >            umask(omask) >         end >      end > >      super(fd, 'wb+') >   end > >   def close >      super >      fclose(@fptr) if @fptr >   end > >   def self.temp_name >      TMPDIR + tmpnam(nil) << '.tmp' >   end > end > > if $0 == __FILE__ >   fh = FileTemp.new >   fh.print 'hello' >   fh.close > end > >