@@ -15,20 +15,24 @@ module OverflowMessageType
15
15
16
16
class MemoryLimitError < StandardError
17
17
attr_reader :message
18
+ attr_reader :trace_point
18
19
attr_reader :backtrace
19
20
20
- def initialize ( message , backtrace = [ ] )
21
+ def initialize ( message , trace_point , backtrace = [ ] )
21
22
@message = message
23
+ @trace_point = trace_point
22
24
@backtrace = backtrace
23
25
end
24
26
end
25
27
26
28
class TimeLimitError < StandardError
27
29
attr_reader :message
30
+ attr_reader :trace_point
28
31
attr_reader :backtrace
29
32
30
- def initialize ( message , backtrace = [ ] )
33
+ def initialize ( message , trace_point , backtrace = [ ] )
31
34
@message = message
35
+ @trace_point = trace_point
32
36
@backtrace = backtrace
33
37
end
34
38
end
@@ -168,47 +172,45 @@ def print_string(string)
168
172
end
169
173
170
174
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
175
176
curr_thread = Thread . current
176
- result = nil
177
- inspect_thread = DebugThread . start {
178
177
178
+ result = nil
179
+ inspect_thread = DebugThread . start do
179
180
start_alloc_size = ObjectSpace . memsize_of_all if ( check_memory_limit )
180
181
start_time = Time . now . to_f
181
182
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
183
186
184
- if ( rand > 0.75 )
185
- curr_time = Time . now . to_f
187
+ curr_time = Time . now . to_f
186
188
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
191
192
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 )
195
196
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 )
200
199
end
201
200
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
206
206
inspect_thread . join
207
- inspect_thread . kill
208
207
return result
209
208
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 " ) )
211
211
return overflow_message_type . call ( e )
212
+ ensure
213
+ inspect_thread . kill if inspect_thread && inspect_thread . alive?
212
214
end
213
215
214
216
def print_variable ( name , value , kind )
@@ -512,4 +514,4 @@ def build_value_attr(escaped_value_str)
512
514
513
515
end
514
516
515
- end
517
+ end
0 commit comments