about summary refs log tree commit homepage
path: root/lib
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-04-01 20:13:21 -0700
committerEric Wong <normalperson@yhbt.net>2009-04-01 21:34:21 -0700
commitac01d8c83b6a3e0d9d0883d9df17f45e208ac101 (patch)
tree54d1cef97e423fdf7fb169f52fcb7415cd125c82 /lib
parente3a6639e270157c4fdc4112a6996c9e7d74acedd (diff)
downloadunicorn-ac01d8c83b6a3e0d9d0883d9df17f45e208ac101.tar.gz
We'll allow before_exec to override that setting, however.

There are cases where someone setting
Logger.new("/path/to/file") will create new file descriptors in
the master process.  This will prevent FD leakage
and a test case (for Linux only) proves it.
Diffstat (limited to 'lib')
-rw-r--r--lib/unicorn.rb19
1 files changed, 14 insertions, 5 deletions
diff --git a/lib/unicorn.rb b/lib/unicorn.rb
index 00012f7..c1d68c1 100644
--- a/lib/unicorn.rb
+++ b/lib/unicorn.rb
@@ -326,15 +326,24 @@ module Unicorn
       end
 
       @reexec_pid = fork do
-        @rd_sig.close if @rd_sig
-        @wr_sig.close if @wr_sig
-        @workers.values.each { |other| other.tempfile.close rescue nil }
-
         ENV.replace(@start_ctx[:environ])
-        ENV['UNICORN_FD'] = @listeners.map { |sock| sock.fileno }.join(',')
+        listener_fds = @listeners.map { |sock| sock.fileno }
+        ENV['UNICORN_FD'] = listener_fds.join(',')
         File.umask(@start_ctx[:umask])
         Dir.chdir(@start_ctx[:cwd])
         cmd = [ @start_ctx[:zero] ] + @start_ctx[:argv]
+
+        # avoid leaking FDs we don't know about, but let before_exec
+        # unset FD_CLOEXEC, if anything else in the app eventually
+        # relies on FD inheritence.
+        purgatory = [] # prevent GC of IO objects
+        (3..1024).each do |io|
+          next if listener_fds.include?(io)
+          io = IO.for_fd(io) rescue nil
+          io or next
+          purgatory << io
+          io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
+        end
         logger.info "executing #{cmd.inspect} (in #{Dir.pwd})"
         @before_exec.call(self) if @before_exec
         exec(*cmd)