11# -*- coding: us-ascii -*-
2- # frozen_string_literal: false
2+ # frozen_string_literal: true
33require "open3"
44require "timeout"
55require_relative "find_executable"
@@ -42,20 +42,79 @@ def rubybin
4242 DEFAULT_SIGNALS = Signal . list
4343 DEFAULT_SIGNALS . delete ( "TERM" ) if /mswin|mingw/ =~ RUBY_PLATFORM
4444
45+ RUBYLIB = ENV [ "RUBYLIB" ]
46+
4547 class << self
46- attr_accessor :subprocess_timeout_scale
48+ attr_accessor :timeout_scale
49+ attr_reader :original_internal_encoding , :original_external_encoding ,
50+ :original_verbose
51+
52+ def capture_global_values
53+ @original_internal_encoding = Encoding . default_internal
54+ @original_external_encoding = Encoding . default_external
55+ @original_verbose = $VERBOSE
56+ end
57+ end
58+
59+ def apply_timeout_scale ( t )
60+ if scale = EnvUtil . timeout_scale
61+ t * scale
62+ else
63+ t
64+ end
65+ end
66+ module_function :apply_timeout_scale
67+
68+ def timeout ( sec , klass = nil , message = nil , &blk )
69+ return yield ( sec ) if sec == nil or sec . zero?
70+ sec = apply_timeout_scale ( sec )
71+ Timeout . timeout ( sec , klass , message , &blk )
72+ end
73+ module_function :timeout
74+
75+ def terminate ( pid , signal = :TERM , pgroup = nil , reprieve = 1 )
76+ reprieve = apply_timeout_scale ( reprieve ) if reprieve
77+
78+ signals = Array ( signal ) . select do |sig |
79+ DEFAULT_SIGNALS [ sig . to_s ] or
80+ DEFAULT_SIGNALS [ Signal . signame ( sig ) ] rescue false
81+ end
82+ signals |= [ :ABRT , :KILL ]
83+ case pgroup
84+ when 0 , true
85+ pgroup = -pid
86+ when nil , false
87+ pgroup = pid
88+ end
89+ while signal = signals . shift
90+ begin
91+ Process . kill signal , pgroup
92+ rescue Errno ::EINVAL
93+ next
94+ rescue Errno ::ESRCH
95+ break
96+ end
97+ if signals . empty? or !reprieve
98+ Process . wait ( pid )
99+ else
100+ begin
101+ Timeout . timeout ( reprieve ) { Process . wait ( pid ) }
102+ rescue Timeout ::Error
103+ end
104+ end
105+ end
106+ $?
47107 end
108+ module_function :terminate
48109
49110 def invoke_ruby ( args , stdin_data = "" , capture_stdout = false , capture_stderr = false ,
50111 encoding : nil , timeout : 10 , reprieve : 1 , timeout_error : Timeout ::Error ,
51112 stdout_filter : nil , stderr_filter : nil ,
52113 signal : :TERM ,
53- rubybin : EnvUtil . rubybin ,
114+ rubybin : EnvUtil . rubybin , precommand : nil ,
54115 **opt )
55- if scale = EnvUtil . subprocess_timeout_scale
56- timeout *= scale if timeout
57- reprieve *= scale if reprieve
58- end
116+ timeout = apply_timeout_scale ( timeout )
117+
59118 in_c , in_p = IO . pipe
60119 out_p , out_c = IO . pipe if capture_stdout
61120 err_p , err_c = IO . pipe if capture_stderr && capture_stderr != :merge_to_stdout
@@ -72,8 +131,11 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr =
72131 if Array === args and Hash === args . first
73132 child_env . update ( args . shift )
74133 end
134+ if RUBYLIB and lib = child_env [ "RUBYLIB" ]
135+ child_env [ "RUBYLIB" ] = [ lib , RUBYLIB ] . join ( File ::PATH_SEPARATOR )
136+ end
75137 args = [ args ] if args . kind_of? ( String )
76- pid = spawn ( child_env , rubybin , *args , **opt )
138+ pid = spawn ( child_env , * precommand , rubybin , *args , **opt )
77139 in_c . close
78140 out_c . close if capture_stdout
79141 err_c . close if capture_stderr && capture_stderr != :merge_to_stdout
@@ -87,35 +149,7 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr =
87149 if ( !th_stdout || th_stdout . join ( timeout ) ) && ( !th_stderr || th_stderr . join ( timeout ) )
88150 timeout_error = nil
89151 else
90- signals = Array ( signal ) . select do |sig |
91- DEFAULT_SIGNALS [ sig . to_s ] or
92- DEFAULT_SIGNALS [ Signal . signame ( sig ) ] rescue false
93- end
94- signals |= [ :ABRT , :KILL ]
95- case pgroup = opt [ :pgroup ]
96- when 0 , true
97- pgroup = -pid
98- when nil , false
99- pgroup = pid
100- end
101- while signal = signals . shift
102- begin
103- Process . kill signal , pgroup
104- rescue Errno ::EINVAL
105- next
106- rescue Errno ::ESRCH
107- break
108- end
109- if signals . empty? or !reprieve
110- Process . wait ( pid )
111- else
112- begin
113- Timeout . timeout ( reprieve ) { Process . wait ( pid ) }
114- rescue Timeout ::Error
115- end
116- end
117- end
118- status = $?
152+ status = terminate ( pid , signal , opt [ :pgroup ] , reprieve )
119153 end
120154 stdout = th_stdout . value if capture_stdout
121155 stderr = th_stderr . value if capture_stderr && capture_stderr != :merge_to_stdout
@@ -126,7 +160,7 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr =
126160 stderr = stderr_filter . call ( stderr ) if stderr_filter
127161 if timeout_error
128162 bt = caller_locations
129- msg = "execution of #{ bt . shift . label } expired"
163+ msg = "execution of #{ bt . shift . label } expired timeout ( #{ timeout } sec) "
130164 msg = Test ::Unit ::Assertions ::FailDesc [ status , msg , [ stdout , stderr ] . join ( "\n " ) ] . ( )
131165 raise timeout_error , msg , bt . map ( &:to_s )
132166 end
@@ -151,30 +185,33 @@ class << self
151185 end
152186
153187 def verbose_warning
154- class << ( stderr = "" )
155- alias write <<
188+ class << ( stderr = "" . dup )
189+ alias write concat
190+ def flush ; end
156191 end
157- stderr , $stderr, verbose , $VERBOSE = $stderr, stderr , $VERBOSE, true
192+ stderr , $stderr = $stderr, stderr
193+ $VERBOSE = true
158194 yield stderr
159195 return $stderr
160196 ensure
161- stderr , $stderr, $VERBOSE = $stderr, stderr , verbose
197+ stderr , $stderr = $stderr, stderr
198+ $VERBOSE = EnvUtil . original_verbose
162199 end
163200 module_function :verbose_warning
164201
165202 def default_warning
166- verbose , $VERBOSE = $VERBOSE , false
203+ $VERBOSE = false
167204 yield
168205 ensure
169- $VERBOSE = verbose
206+ $VERBOSE = EnvUtil . original_verbose
170207 end
171208 module_function :default_warning
172209
173210 def suppress_warning
174- verbose , $VERBOSE = $VERBOSE , nil
211+ $VERBOSE = nil
175212 yield
176213 ensure
177- $VERBOSE = verbose
214+ $VERBOSE = EnvUtil . original_verbose
178215 end
179216 module_function :suppress_warning
180217
@@ -187,26 +224,18 @@ def under_gc_stress(stress = true)
187224 module_function :under_gc_stress
188225
189226 def with_default_external ( enc )
190- verbose , $VERBOSE = $VERBOSE, nil
191- origenc , Encoding . default_external = Encoding . default_external , enc
192- $VERBOSE = verbose
227+ suppress_warning { Encoding . default_external = enc }
193228 yield
194229 ensure
195- verbose , $VERBOSE = $VERBOSE, nil
196- Encoding . default_external = origenc
197- $VERBOSE = verbose
230+ suppress_warning { Encoding . default_external = EnvUtil . original_external_encoding }
198231 end
199232 module_function :with_default_external
200233
201234 def with_default_internal ( enc )
202- verbose , $VERBOSE = $VERBOSE, nil
203- origenc , Encoding . default_internal = Encoding . default_internal , enc
204- $VERBOSE = verbose
235+ suppress_warning { Encoding . default_internal = enc }
205236 yield
206237 ensure
207- verbose , $VERBOSE = $VERBOSE, nil
208- Encoding . default_internal = origenc
209- $VERBOSE = verbose
238+ suppress_warning { Encoding . default_internal = EnvUtil . original_internal_encoding }
210239 end
211240 module_function :with_default_internal
212241
@@ -274,10 +303,9 @@ class << self
274303 attr_reader :ruby
275304 end
276305 dir = File . dirname ( ruby )
277- name = File . basename ( ruby , CONFIG [ 'EXEEXT' ] )
278306 CONFIG [ 'bindir' ] = dir
279- CONFIG [ 'ruby_install_name' ] = name
280- CONFIG [ 'RUBY_INSTALL_NAME' ] = name
281307 Gem ::ConfigMap [ :bindir ] = dir if defined? ( Gem ::ConfigMap )
282308 end
283309end
310+
311+ EnvUtil . capture_global_values
0 commit comments