From: Nobuyoshi Nakada Date: 2009-10-23T17:55:16+09:00 Subject: [ruby-core:26248] Re: [Bug #2250] IO::for_fd() objects' finalization dangerously closes underlying fds Hi, At Fri, 23 Oct 2009 07:05:23 +0900, Mike Pomraning wrote in [ruby-core:26242]: > IMHO, if you know enough about fds to dress one up as an > IO, you know enough to judge whether Ruby should close it > for you. Ruby can never know this a priori, and in most > cases I can think of, it isn't ever desired. I don't think it is acceptable, because of backward compatibility. Excerpt from rdoc of Socket#sysaccept: client_fd, client_sockaddr = socket.sysaccept client_socket = Socket.for_fd( client_fd ) This example expects the fd will get closed automatically. > Indeed, a 2002 commit message suggests that not closing > should be the default: > > | Revision 2312 matz, 04/01/2002 01:39 AM > | > | * re.c (match_setter): it's OK to assign nil to $~. > | * io.c (rb_io_fptr_cleanup): do not close IO created by for_fd(). > | * io.c (rb_io_initialize): mark IO created by for_fd > | * ext/socket/socket.c (bsock_s_for_fd): ditto. It's been removed soon. ------------------------------------------------------------------------ r2375 | matz | 2002-04-15 16:48:47 +0900 (Mon, 15 Apr 2002) | 9 lines * io.c (rb_io_fptr_cleanup): should close IO created by IO.new(fd). * rubyio.h: remove FMODE_FDOPEN ------------------------------------------------------------------------ > > Basically, such extension libraries should expose IO > > instances, but not file descriptors. > > Where practicable, yes. Respectfully and UIMS, however, > I think this asks too much of ext library authors. Hmm, there is no one-liner function, indeed. #ifdef GetWriteFile static void fptr_finalize_noclose(rb_io_t *fptr, int noraise) { fflush(GetWriteFile(fptr)); } #endif VALUE make_noclose_io(int fd, int mode) { VALUE io; rb_io_t *fptr; MakeOpenFile(io, fptr); fptr->fd = fd; #ifdef GetWriteFile fptr->finalize = fptr_finalize_noclose; #else mode |= FMODE_PREP; #endif fptr->mode |= mode; return io; } > Either they must wait for and explicitly use your > autoclose feature, or must manage their own IO object > references -- and the binding authors themselves may > only have a "naked" fd to play with, may not know when > the underlying library chooses to call close(), etc. If the fd is bound to an IO instance or not, the library can close it always. -- Nobu Nakada