Subject:
[ruby-ffi] Unable to detect failure with reentrant function on Linux
From:
Daniel Berger
Date:
6/12/10 9:38 PM
To:
ruby-ffi

Hi,

Ruby 1.8.6
FFI 0.6.3

I cannot seem to detect a failure with getprotobynumber_r on Linux
when I intentionally pass it a bogus value. Instead, it returns the
last value of /etc/protocols.

What am I doing wrong?

require 'ffi'

module Net
  class Proto
    extend FFI::Library

    unless RUBY_PLATFORM == 'java' && JRUBY_VERSION.to_f < 1.5
      ffi_lib(FFI::Library::LIBC)
    end

    class ProtocolStruct < FFI::Struct
      layout(
        :p_name,    :string,
        :p_aliases, :pointer,
        :p_proto,   :int
      )
    end

    attach_function 'setprotoent', [:int], :void
    attach_function 'endprotoent', [], :void
    attach_function 'getprotobynumber_r',
[:int, :pointer, :string, :long, :pointer], :int

    def self.getprotobynumber(protocol)
      raise TypeError unless protocol.is_a?(Integer)

      pptr = FFI::MemoryPointer.new(ProtocolStruct.size)
      qptr = FFI::MemoryPointer.new(ProtocolStruct.size)
      buf  = 1.chr * 1024

      begin
        setprotoent(0)
        int = getprotobynumber_r(protocol, pptr, buf, buf.size, qptr)
      ensure
        endprotoent()
      end

      int > 0 || qptr.null? ? nil : ProtocolStruct.new(pptr)[:p_name]
    end
  end
end

p Net::Proto.getprotobynumber(999999999) # should be nil

Regards,

Dan