Subject: Re: [ruby-ffi] Unable to detect failure with reentrant function on Linux |
From: Wayne Meissner |
Date: 6/12/10 10:24 PM |
To: ruby-ffi@googlegroups.com |
A couple of things: 1) You should map getprotobynumber_r as: attach_function 'getprotobynumber_r', [:int, :pointer, :pointer, :long, :pointer], :int 2) and call it like so: # getprotobynumber_r will use the buffer you pass in as the allocation area for the names # of the protocol, so allocate some native memory for it. namebuf = FFI::MemoryPointer.new(:char, 1024, false) pstruct = ProtocolStruct.new ptr = FFI::MemoryPointer.new(:pointer) rc = getprotobynumber_r(protocol, pstruct, namebuf, 1024, qptr) 3) a return val of 0 signifies success, and pstruct will be filled out with the data. For non-zero returns, you should probably check errno, and raise an exception if it is anything other than the not-found case. return rc == 0 && !qptr.get_pointer(0).null? ? pstruct[:p_name] : nil Note: the signature for getprotobynumber_r is different across linux, solaris and aix, so its a bit nasty, unless you only care about linux, or you have code for each of those cases. On 13 June 2010 12:38, Daniel Berger <djberg96@gmail.com> wrote:
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