@@ -15,20 +15,24 @@ module OverflowMessageType
1515
1616 class MemoryLimitError < StandardError
1717 attr_reader :message
18+ attr_reader :trace_point
1819 attr_reader :backtrace
1920
20- def initialize ( message , backtrace = [ ] )
21+ def initialize ( message , trace_point , backtrace = [ ] )
2122 @message = message
23+ @trace_point = trace_point
2224 @backtrace = backtrace
2325 end
2426 end
2527
2628 class TimeLimitError < StandardError
2729 attr_reader :message
30+ attr_reader :trace_point
2831 attr_reader :backtrace
2932
30- def initialize ( message , backtrace = [ ] )
33+ def initialize ( message , trace_point , backtrace = [ ] )
3134 @message = message
35+ @trace_point = trace_point
3236 @backtrace = backtrace
3337 end
3438 end
@@ -168,47 +172,45 @@ def print_string(string)
168172 end
169173
170174 def exec_with_allocation_control ( value , memory_limit , time_limit , exec_method , overflow_message_type )
171- check_memory_limit = true
172- if ( defined? ( JRUBY_VERSION ) || ENV [ 'DEBUGGER_MEMORY_LIMIT' ] . to_i <= 0 )
173- check_memory_limit = false
174- end
175+ check_memory_limit = !defined? ( JRUBY_VERSION ) && ENV [ 'DEBUGGER_MEMORY_LIMIT' ] . to_i > 0
175176 curr_thread = Thread . current
176- result = nil
177- inspect_thread = DebugThread . start {
178177
178+ result = nil
179+ inspect_thread = DebugThread . start do
179180 start_alloc_size = ObjectSpace . memsize_of_all if ( check_memory_limit )
180181 start_time = Time . now . to_f
181182
182- trace = TracePoint . new ( :c_call , :call ) do |tp |
183+ trace_point = TracePoint . new ( :c_call , :call ) do | |
184+ next unless Thread . current == inspect_thread
185+ next unless rand > 0.75
183186
184- if ( rand > 0.75 )
185- curr_time = Time . now . to_f
187+ curr_time = Time . now . to_f
186188
187- if ( ( curr_time - start_time ) * 1e3 > time_limit )
188- curr_thread . raise TimeLimitError . new ( "Timeout: evaluation of #{ exec_method } took longer than #{ time_limit } ms." , caller . to_a )
189- inspect_thread . kill
190- end
189+ if ( curr_time - start_time ) * 1e3 > time_limit
190+ curr_thread . raise TimeLimitError . new ( "Timeout: evaluation of #{ exec_method } took longer than #{ time_limit } ms." , caller . to_a , trace_point )
191+ end
191192
192- if ( check_memory_limit )
193- curr_alloc_size = ObjectSpace . memsize_of_all
194- start_alloc_size = curr_alloc_size if ( curr_alloc_size < start_alloc_size )
193+ if check_memory_limit
194+ curr_alloc_size = ObjectSpace . memsize_of_all
195+ start_alloc_size = curr_alloc_size if ( curr_alloc_size < start_alloc_size )
195196
196- if ( curr_alloc_size - start_alloc_size > 1e6 * memory_limit )
197- curr_thread . raise MemoryLimitError . new ( "Out of memory: evaluation of #{ exec_method } took more than #{ memory_limit } mb." , caller . to_a )
198- inspect_thread . kill
199- end
197+ if curr_alloc_size - start_alloc_size > 1e6 * memory_limit
198+ curr_thread . raise MemoryLimitError . new ( "Out of memory: evaluation of #{ exec_method } took more than #{ memory_limit } mb." , caller . to_a , trace_point )
200199 end
201200 end
202- end . enable {
203- result = value . send exec_method
204- }
205- }
201+ end
202+ trace_point . enable
203+ result = value . send exec_method
204+ trace_point . disable
205+ end
206206 inspect_thread . join
207- inspect_thread . kill
208207 return result
209208 rescue MemoryLimitError , TimeLimitError => e
210- print_debug ( e . message + "\n " + e . backtrace . map { |l | "\t #{ l } " } . join ( "\n " ) )
209+ e . trace_point . disable
210+ print_debug ( e . message + "\n " + e . backtrace . map { |l | "\t #{ l } " } . join ( "\n " ) )
211211 return overflow_message_type . call ( e )
212+ ensure
213+ inspect_thread . kill if inspect_thread && inspect_thread . alive?
212214 end
213215
214216 def print_variable ( name , value , kind )
@@ -512,4 +514,4 @@ def build_value_attr(escaped_value_str)
512514
513515 end
514516
515- end
517+ end
0 commit comments