about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <yahns-public@yhbt.net>2017-03-27 20:59:54 +0000
committerEric Wong <e@80x24.org>2017-04-03 19:57:22 +0000
commit5bc5f36b5e5aef6340d94f8809122ac81fe466a2 (patch)
treedde3339b08548d0bd87558f746916ad915cf37c2
parent9ad151e4aa6e3120f3fb53f5e82d35ba57e45bb6 (diff)
downloadyahns-5bc5f36b5e5aef6340d94f8809122ac81fe466a2.tar.gz
Remove false statements about close-on-exec being cleared in the
parent process (verified via strace) and refactor the code to
take full advantage of options for Process.spawn and Process.exec.

This avoids unnecessary CoW traffic for the common case where
before_exec is unset.
-rw-r--r--lib/yahns/server.rb33
1 files changed, 16 insertions, 17 deletions
diff --git a/lib/yahns/server.rb b/lib/yahns/server.rb
index 00e5f15..5411c48 100644
--- a/lib/yahns/server.rb
+++ b/lib/yahns/server.rb
@@ -237,24 +237,23 @@ class Yahns::Server # :nodoc:
       end
     end
 
-    # We cannot use Process.spawn here because of redirects + close-on-exec
-    # We must keep close_on_exec=true in the parent process and only set
-    # close_on_exec=false in the child.  There must be no opportunity
-    # for the user app to ever get a listen socket with close_on_exec=false
-    @reexec_pid = fork do
-      redirects = {}
-      @listeners.each do |sock|
-        sock.close_on_exec = false
-        redirects[sock.fileno] = sock
+    opt = {}
+    @listeners.each { |sock| opt[sock.fileno] = sock }
+    env = ENV.to_hash
+    env['YAHNS_FD'] = opt.keys.join(',')
+    opt[:close_others] = true
+    cmd = [ Yahns::START[0] ].concat(Yahns::START[:argv])
+    dir = @config.value(:working_directory) || Yahns::START[:cwd]
+    @logger.info "spawning #{cmd.inspect} (in #{dir})"
+    @reexec_pid = if @before_exec
+      fork do
+        Dir.chdir(dir)
+        @before_exec.call(cmd)
+        exec(env, *cmd, opt)
       end
-      ENV['YAHNS_FD'] = redirects.keys.join(',')
-      redirects[:close_others] = true
-      Dir.chdir(@config.value(:working_directory) || Yahns::START[:cwd])
-      cmd = [ Yahns::START[0] ].concat(Yahns::START[:argv])
-      @logger.info "executing #{cmd.inspect} (in #{Dir.pwd})"
-      @before_exec.call(cmd) if @before_exec
-      cmd << redirects
-      exec(*cmd)
+    else
+      opt[:chdir] = dir
+      spawn(env, *cmd, opt)
     end
   end