How to find and close opened file descriptor

During my testing, I found that ruby doesn't create IO object for each
opened file descriptor which are inherited from parent process. So we
have to close all these opened file descriptor except stdin, stdout and
stderr by following way:

     3.upto(1023) do |fd|
        begin
          if io = IO::new(fd)
            io.close
          end
        rescue
        end
      end

But I really don't like this way. Is there better way that I can find
all opened file descriptors.

And now I am assuming the maximum file no is 1023. Is there any way that
I can get the maximum file no?

Thanks.

···

--
Posted via http://www.ruby-forum.com/.

And now I am assuming the maximum file no is 1023. Is there any way that
I can get the maximum file no?

You could run a loop at the beginning of your script which detects it :slight_smile:

count = 0
all =
begin
loop { all << File.open('test','w') }
rescue Exception
count = all.length
for file in all do; file.close; end
end
count

But getting back to your original question, another way to close
descriptors is
GC.each_object(IO) do |io| io.close; end

I guess. Not totally sure what you mean by "doesnt create file
descriptors for each inherited object" ?
Thanks.
-=r

···

--
Posted via http://www.ruby-forum.com/\.

I believe this is the standard idiom on *nix type systems to close all file descriptors when you have no particular knowledge of which ones are open.

In other words there is no standard way to ask the OS for a list of open descriptors via a simple system call.

A possible alternative is to parse the output of utilities like 'lsof' to determine what file descriptors are open or to dig into the various platform specific ways that those utilities query the kernel for this information.

Gary Wright

···

On May 7, 2009, at 11:54 AM, Oliver Peng wrote:

During my testing, I found that ruby doesn't create IO object for each
opened file descriptor which are inherited from parent process. So we
have to close all these opened file descriptor except stdin, stdout and
stderr by following way:

    3.upto(1023) do |fd|
       begin
         if io = IO::new(fd)
           io.close
         end
       rescue
       end
     end

But I really don't like this way. Is there better way that I can find
all opened file descriptors.

The io-extra library might be able to help you, depending on your
platform.

gem install io-extra.

Take a look at the IO.closefrom and IO.fdwalk methods.

Regards,

Dan

···

On May 7, 9:54 am, Oliver Peng <oliver.p...@skywave.com> wrote:

During my testing, I found that ruby doesn't create IO object for each
opened file descriptor which are inherited from parent process. So we
have to close all these opened file descriptor except stdin, stdout and
stderr by following way:

 3\.upto\(1023\) do |fd|
    begin
      if io = IO::new\(fd\)
        io\.close
      end
    rescue
    end
  end

But I really don't like this way. Is there better way that I can find
all opened file descriptors.

And now I am assuming the maximum file no is 1023. Is there any way that
I can get the maximum file no?

Roger Pack wrote:

And now I am assuming the maximum file no is 1023. Is there any way that
I can get the maximum file no?

You could run a loop at the beginning of your script which detects it :slight_smile:

count = 0
all =
begin
loop { all << File.open('test','w') }
rescue Exception
count = all.length
for file in all do; file.close; end
end
count

But getting back to your original question, another way to close
descriptors is
GC.each_object(IO) do |io| io.close; end

I guess. Not totally sure what you mean by "doesnt create file
descriptors for each inherited object" ?
Thanks.
-=r

At first, I also try to find all IO objects and close. Here is the code:

ObjectSpace.each_object(IO) do |io|
    begin
      unless io.closed?
        io.close
      end
    rescue ::Exception
    end
end

But it doesn't work because ruby doesn't create IO object for the open
file descriptor which are inherited from parent process.

···

--
Posted via http://www.ruby-forum.com/\.

I believe this is the standard idiom on *nix type systems to close all
file descriptors when you have no particular knowledge of which ones
are open.

I think that's right except for maybe solaris has a helper or something,
but there's no standard.
-=r

···

--
Posted via http://www.ruby-forum.com/\.

You should probably describe how your parent process is opening these file descriptors as clearly it's not via objects in the IO hierarchy or they would be accessible in the child process. As a general rule though, if you have control over where and when the file descriptors are coming into play you can use the IO.for_fd(file_descriptor) method and store them in a *shudder* global variable or constant...

  OPEN_FILES =
  ...
  fd = some_method_that_opens_file_and_returns_descriptor
  OPEN_FILES << IO.for_fd(fd)
  ...

Then in the spawned child process closing these would be as simple as:

  OPEN_FILES.each { |file| file.close }

Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net

···

On 8 May 2009, at 14:55, Oliver Peng wrote:

At first, I also try to find all IO objects and close. Here is the code:

ObjectSpace.each_object(IO) do |io|
   begin
     unless io.closed?
       io.close
     end
   rescue ::Exception
   end
end

But it doesn't work because ruby doesn't create IO object for the open
file descriptor which are inherited from parent process.

----
raise ArgumentError unless @reality.responds_to? :reason