diff --git a/lib/kontena/plugin/shell/session.rb b/lib/kontena/plugin/shell/session.rb index 5d2422d..3c969d3 100644 --- a/lib/kontena/plugin/shell/session.rb +++ b/lib/kontena/plugin/shell/session.rb @@ -27,6 +27,18 @@ def run_command(buf) tokens = buf.split(/\s(?=(?:[^"]|"[^"]*")*$)/).map(&:strip) runner = Shell.command(tokens.first) || Shell.command(context.first) || Kontena::Plugin::Shell::KontenaCommand command = runner.new(context, tokens, self) + if fork_supported? + execute_with_fork(command) + else + execute_with_thread(command) + end + end + + def fork_supported? + Process.respond_to?(:fork) + end + + def execute_with_thread(command) old_trap = trap('INT', Proc.new { Thread.main[:command_thread] && Thread.main[:command_thread].kill }) Thread.main[:command_thread] = Thread.new do command.run @@ -35,6 +47,33 @@ def run_command(buf) trap('INT', old_trap) end + def execute_with_fork(command) + start = Time.now + pid = fork do + Process.setproctitle("kosh-runner") + command.run + end + trap('INT') { + begin + Process.kill('TERM', pid) + rescue Errno::ESRCH + raise SignalException, 'SIGINT' + end + } + Process.waitpid(pid) + if config_file_modified_since?(start) + puts "" + puts pastel.yellow("Config file has been modified, reloading configuration") + puts "" + config.reset_instance + end + end + + def config_file_modified_since?(time) + return false unless config.config_file_available? + return true if File.mtime(config.config_filename) >= time + end + def run puts File.read(__FILE__)[/__END__$(.*)/m, 1] puts "Kontena Shell v#{Kontena::Plugin::Shell::VERSION} (c) 2017 Kontena" diff --git a/spec/kontena/plugin/shell/session_spec.rb b/spec/kontena/plugin/shell/session_spec.rb index ae134cf..a8a7600 100644 --- a/spec/kontena/plugin/shell/session_spec.rb +++ b/spec/kontena/plugin/shell/session_spec.rb @@ -8,6 +8,7 @@ let(:subject) { described_class.new(context) } it 'runs commands' do + allow(subject).to receive(:fork_supported?).and_return(false) expect(Readline).to receive(:readline).and_return('exit') expect{subject.run}.to output(/Bye/).to_stdout.and raise_error(SystemExit) end