Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Close open file descriptors when calling Process.spawn #1904

Closed
wants to merge 2 commits into
from
Jump to file or symbol
Failed to load files and symbols.
+27 −4
Split
View
@@ -454,13 +454,27 @@ def self.setup(io, fd, mode=nil, sync=false)
end
end
+ update_max_open_fd(fd)
+
io.descriptor = fd
io.mode = mode || cur_mode
io.sync = !!sync
io.sync ||= STDOUT.fileno == fd if STDOUT.respond_to?(:fileno)
io.sync ||= STDERR.fileno == fd if STDERR.respond_to?(:fileno)
end
+ @max_open_fd = 2
+
+ def self.update_max_open_fd(*fds)
+ fds.each do |fd|
+ @max_open_fd = fd if fd > @max_open_fd
+ end
+ end
+
+ def self.max_open_fd
+ @max_open_fd
+ end
+
##
# Obtains a new duplicate descriptor for the current one.
def initialize_copy(original) # :nodoc:
View
@@ -233,9 +233,11 @@ def self.pipe
begin
connect_pipe(lhs, rhs)
+ ::IO.update_max_open_fd(lhs.fileno, rhs.fileno)
rescue Errno::EMFILE
GC.run(true)
connect_pipe(lhs, rhs)
+ ::IO.update_max_open_fd(lhs.fileno, rhs.fileno)
end
lhs.sync = true
View
@@ -673,9 +673,11 @@ def self.pipe(external_encoding=nil, internal_encoding=nil)
begin
connect_pipe(lhs, rhs)
+ ::IO.update_max_open_fd(lhs.fileno, rhs.fileno)
rescue Errno::EMFILE
GC.run(true)
connect_pipe(lhs, rhs)
+ ::IO.update_max_open_fd(lhs.fileno, rhs.fileno)
end
external_encoding ||= Encoding.default_external
@@ -288,6 +288,15 @@ def self.exec(*args)
def self.spawn(*args)
env, prog, argv, redirects, options = Rubinius::Spawn.extract_arguments(*args)
+ unless options[:close_others] == false
+ 3.upto(IO.max_open_fd).each do |fd|
+ begin
+ IO.for_fd(fd, :autoclose => false).close_on_exec = true
+ rescue Errno::EBADF
+ end
+ end
+ end
+
IO.pipe do |read, write|
pid = Process.fork do
read.close
View
@@ -199,7 +199,6 @@ def popen2e(*cmd, &block)
module_function :popen2e
def popen_run(cmd, opts, child_io, parent_io) # :nodoc:
- parent_io.each {|io| io.close_on_exec = true }
pid = spawn(*cmd, opts)
wait_thr = Process.detach(pid)
child_io.each {|io| io.close }
@@ -1,2 +0,0 @@
-fails:Kernel#spawn closes file descriptors >= 3 in the child process
-fails:Kernel.spawn closes file descriptors >= 3 in the child process
@@ -1 +0,0 @@
-fails:Process.spawn closes file descriptors >= 3 in the child process