Feature #2250


IO::for_fd() objects' finalization dangerously closes underlying fds

Added by pilcrow (Mike Pomraning) almost 14 years ago. Updated over 4 years ago.

Target version:



  1. Expected behavior:

An IO object created by IO::for_fd(a_socket_fd) should not call close(2) on its underlying fd upon finalization. The object did not allocate the fd, and so cannot safely nor politely close it.

  1. Observed behavior:

Instead, an IO object created by IO::for_fd(a_socket_fd) will attempt to close(2) its underlying socket fd upon finalization.

  1. How to reproduce:

The attached script and trivial extension module demonstrate that an IO::for_fd()-created object may secretly close(2) the fd behind an innocent object, causing operations on that File object to fail for no reason apparent in (nor knowable to) the ruby code. On 32-bit Linux under ruby-1.9 (or 1.8. for that matter), it produces:

$ ruby io-finalize.rb
#<File::Stat dev=0x11, ino=1193, ....
Finalizing an IO::for_fd() object...
io-finalize.rb:29:in `stat': Bad file descriptor - /dev/null (Errno::EBADF)
from io-finalize.rb:29

  1. Why this is very bad:

In practice, fds passed to for_fd() may be exposed by extension modules, which modules are responsible for the cleanup of the file descriptor. Thus, close(2)ing upon finalization may rudely and dangerously close a file descriptor already closed and reassigned to some unrelated bit of code, causing baffling, "action at a distance" failures.

Indeed, the script to reproduce this failure simulates the experience of two different users of two different ruby bindings to PostgreSQL's libpq (ruby-pg and dbd-altpg), whose uses of [ IO.for_fd(pg_underlying_socket) ] ... ) thus caused failures elsewhere.

Casual testing suggests that this behavior also applies to at least one other non-regular file type, the FIFO.


syssocket.c (605 Bytes) syssocket.c pilcrow (Mike Pomraning), 10/22/2009 12:43 PM
io-finalize.rb (853 Bytes) io-finalize.rb pilcrow (Mike Pomraning), 10/22/2009 12:43 PM

Related issues 1 (0 open1 closed)

Related to Backport193 - Backport #5850: Backport r34129, r34250, r34252 and r34253 ( Failure test/ruby/test_io.rb )Closed01/06/2012Actions

Also available in: Atom PDF