Last active
November 9, 2025 05:17
-
-
Save pasela/9392115 to your computer and use it in GitHub Desktop.
Revisions
-
pasela revised this gist
Mar 13, 2014 . 1 changed file with 3 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -87,10 +87,11 @@ def capture3_with_timeout(*cmd) end rescue Timeout::Error result[:timeout] = true pid = spawn_opts[:pgroup] ? -result[:pid] : result[:pid] Process.kill(opts[:signal], pid) if opts[:kill_after] unless wait_thr.join(opts[:kill_after]) Process.kill(:KILL, pid) end end ensure -
pasela revised this gist
Mar 7, 2014 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -70,7 +70,7 @@ def capture3_with_timeout(*cmd) wait_thr = nil begin Timeout.timeout(opts[:timeout]) do result[:pid] = spawn(*cmd, spawn_opts) wait_thr = Process.detach(result[:pid]) in_r.close -
pasela created this gist
Mar 6, 2014 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,105 @@ # encoding: utf-8 require "timeout" # Capture the standard output and the standard error of a command. # Almost same as Open3.capture3 method except for timeout handling and return value. # See Open3.capture3. # # result = capture3_with_timeout([env,] cmd... [, opts]) # # The arguments env, cmd and opts are passed to Process.spawn except # opts[:stdin_data], opts[:binmode], opts[:timeout], opts[:signal] # and opts[:kill_after]. See Process.spawn. # # If opts[:stdin_data] is specified, it is sent to the command's standard input. # # If opts[:binmode] is true, internal pipes are set to binary mode. # # If opts[:timeout] is specified, SIGTERM is sent to the command after specified seconds. # # If opts[:signal] is specified, it is used instead of SIGTERM on timeout. # # If opts[:kill_after] is specified, also send a SIGKILL after specified seconds. # it is only sent if the command is still running after the initial signal was sent. # # The return value is a Hash as shown below. # # { # :pid => PID of the command, # :status => Process::Status of the command, # :stdout => the standard output of the command, # :stderr => the standard error of the command, # :timeout => whether the command was timed out, # } def capture3_with_timeout(*cmd) spawn_opts = Hash === cmd.last ? cmd.pop.dup : {} opts = { :stdin_data => spawn_opts.delete(:stdin_data) || "", :binmode => spawn_opts.delete(:binmode) || false, :timeout => spawn_opts.delete(:timeout), :signal => spawn_opts.delete(:signal) || :TERM, :kill_after => spawn_opts.delete(:kill_after), } in_r, in_w = IO.pipe out_r, out_w = IO.pipe err_r, err_w = IO.pipe in_w.sync = true if opts[:binmode] in_w.binmode out_r.binmode err_r.binmode end spawn_opts[:in] = in_r spawn_opts[:out] = out_w spawn_opts[:err] = err_w result = { :pid => nil, :status => nil, :stdout => nil, :stderr => nil, :timeout => false, } out_reader = nil err_reader = nil wait_thr = nil begin timeout(opts[:timeout]) do result[:pid] = spawn(*cmd, spawn_opts) wait_thr = Process.detach(result[:pid]) in_r.close out_w.close err_w.close out_reader = Thread.new { out_r.read } err_reader = Thread.new { err_r.read } in_w.write opts[:stdin_data] in_w.close result[:status] = wait_thr.value end rescue Timeout::Error result[:timeout] = true Process.kill(opts[:signal], result[:pid]) if opts[:kill_after] unless wait_thr.join(opts[:kill_after]) Process.kill(:KILL, result[:pid]) end end ensure result[:status] = wait_thr.value if wait_thr result[:stdout] = out_reader.value if out_reader result[:stderr] = err_reader.value if err_reader out_r.close unless out_r.closed? err_r.close unless err_r.closed? end result end