module RubyCliDaemon
Constants
- TIMEOUT
- VERSION
Public Class Methods
install(path)
click to toggle source
# File lib/ruby_cli_daemon.rb, line 10 def install(path) File.unlink(path) if File.exist?(path) File.symlink(File.expand_path("../bin/ruby-cli-daemon.sh", __dir__), path) end
start(socket, executable)
click to toggle source
# File lib/ruby_cli_daemon.rb, line 15 def start(socket, executable) path = preload_gem(executable) server = create_socket(socket) # do this last, it signals we are ready loop do return unless IO.select([server], nil, nil, TIMEOUT) # execute the gems binary in a fork _, status = Process.wait2(fork do File.write("#{socket}.pid", Process.pid) # uncovered replace_env server # uncovered load path # uncovered end) # send back exit status File.write("#{socket}.status", status.exitstatus || 127) end ensure # signal that this program is done so ruby-sli-daemon.sh restarts it File.unlink socket if File.exist?(socket) end
Private Class Methods
create_socket(socket)
click to toggle source
# File lib/ruby_cli_daemon.rb, line 92 def create_socket(socket) FileUtils.mkdir_p(File.dirname(socket)) UNIXServer.new(socket) end
find_gem_spec(executable)
click to toggle source
# File lib/ruby_cli_daemon.rb, line 59 def find_gem_spec(executable) spec = Gem::Specification.detect { |s| s.executables.include?(executable) } [spec.name, spec.bin_file(executable)] if spec # need something we can send out from fork end
fork_with_return() { || ... }
click to toggle source
# File lib/ruby_cli_daemon.rb, line 64 def fork_with_return read, write = IO.pipe Process.wait(fork do read.close begin Marshal.dump(yield, write) rescue StandardError => e Marshal.dump(e, write) end end) write.close result = Marshal.load(read) result.is_a?(StandardError) ? raise(result) : result end
preload_gem(executable)
click to toggle source
preload the libraries we'll need, to speed up execution first try with bundler and then without
# File lib/ruby_cli_daemon.rb, line 41 def preload_gem(executable) name, path = fork_with_return do require "bundler/setup" find_gem_spec(executable) end if name require "bundler/setup" else name, path = find_gem_spec(executable) raise "No gem with executable #{executable} found" unless name end require name GC.start # https://bugs.ruby-lang.org/issues/15878 path end
replace_env(server)
click to toggle source
# File lib/ruby_cli_daemon.rb, line 79 def replace_env(server) connection = server.accept begin STDOUT.reopen connection.recv_io STDERR.reopen connection.recv_io STDIN.reopen connection.recv_io ARGV.replace connection.gets.shellsplit ENV.replace Hash[connection.read.split("--RCD--").map { |s| s.split(/ /, 2) }] ensure connection.close # not sure if this is necessary end end