debug 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/debug/session.rb CHANGED
@@ -7,7 +7,7 @@ return if ENV['RUBY_DEBUG_ENABLE'] == '0'
7
7
  if $0.end_with?('bin/bundle') && ARGV.first == 'exec'
8
8
  trace_var(:$0) do |file|
9
9
  trace_var(:$0, nil)
10
- if /-r (#{__dir__}\S+)/ =~ ENV['RUBYOPT']
10
+ if /-r (#{Regexp.escape(__dir__)}\S+)/ =~ ENV['RUBYOPT']
11
11
  lib = $1
12
12
  $LOADED_FEATURES.delete_if{|path| path.start_with?(__dir__)}
13
13
  ENV['RUBY_DEBUG_INITIAL_SUSPEND_PATH'] = file
@@ -31,7 +31,7 @@ $LOADED_FEATURES << 'debug.rb'
31
31
  $LOADED_FEATURES << File.expand_path(File.join(__dir__, '..', 'debug.rb'))
32
32
  require 'debug' # invalidate the $LOADED_FEATURE cache
33
33
 
34
- require 'json' if ENV['RUBY_DEBUG_TEST_MODE']
34
+ require 'json' if ENV['RUBY_DEBUG_TEST_UI'] == 'terminal'
35
35
 
36
36
  class RubyVM::InstructionSequence
37
37
  def traceable_lines_norec lines
@@ -56,23 +56,22 @@ class RubyVM::InstructionSequence
56
56
 
57
57
  def type
58
58
  self.to_a[9]
59
- end
60
-
61
- def argc
62
- self.to_a[4][:arg_size]
63
- end
59
+ end unless method_defined?(:type)
64
60
 
65
- def locals
66
- self.to_a[10]
67
- end
61
+ def parameters_symbols
62
+ ary = self.to_a
63
+ argc = ary[4][:arg_size]
64
+ locals = ary.to_a[10]
65
+ locals[0...argc]
66
+ end unless method_defined?(:parameters_symbols)
68
67
 
69
68
  def last_line
70
69
  self.to_a[4][:code_location][2]
71
- end
70
+ end unless method_defined?(:last_line)
72
71
 
73
72
  def first_line
74
73
  self.to_a[4][:code_location][0]
75
- end
74
+ end unless method_defined?(:first_line)
76
75
  end
77
76
 
78
77
  module DEBUGGER__
@@ -82,8 +81,10 @@ module DEBUGGER__
82
81
  class Session
83
82
  attr_reader :intercepted_sigint_cmd, :process_group
84
83
 
85
- def initialize ui
86
- @ui = ui
84
+ include Color
85
+
86
+ def initialize
87
+ @ui = nil
87
88
  @sr = SourceRepository.new
88
89
  @bps = {} # bp.key => bp
89
90
  # [file, line] => LineBreakpoint
@@ -104,13 +105,13 @@ module DEBUGGER__
104
105
  @intercept_trap_sigint = false
105
106
  @intercepted_sigint_cmd = 'DEFAULT'
106
107
  @process_group = ProcessGroup.new
107
- @subsession = nil
108
+ @subsession_stack = []
108
109
 
109
110
  @frame_map = {} # for DAP: {id => [threadId, frame_depth]} and CDP: {id => frame_depth}
110
111
  @var_map = {1 => [:globals], } # {id => ...} for DAP
111
112
  @src_map = {} # {id => src}
112
113
 
113
- @script_paths = [File.absolute_path($0)] # for CDP
114
+ @scr_id_map = {} # for CDP
114
115
  @obj_map = {} # { object_id => ... } for CDP
115
116
 
116
117
  @tp_thread_begin = nil
@@ -120,9 +121,6 @@ module DEBUGGER__
120
121
  @tp_load_script.enable
121
122
 
122
123
  @thread_stopper = thread_stopper
123
-
124
- activate
125
-
126
124
  self.postmortem = CONFIG[:postmortem]
127
125
  end
128
126
 
@@ -134,15 +132,13 @@ module DEBUGGER__
134
132
  @bps.has_key? [file, line]
135
133
  end
136
134
 
137
- def activate on_fork: false
135
+ def activate ui = nil, on_fork: false
136
+ @ui = ui if ui
137
+
138
138
  @tp_thread_begin&.disable
139
139
  @tp_thread_begin = nil
140
140
 
141
- if on_fork
142
- @ui.activate self, on_fork: true
143
- else
144
- @ui.activate self, on_fork: false
145
- end
141
+ @ui.activate self, on_fork: on_fork
146
142
 
147
143
  q = Queue.new
148
144
  @session_server = Thread.new do
@@ -215,6 +211,7 @@ module DEBUGGER__
215
211
  q << true
216
212
 
217
213
  when :init
214
+ enter_subsession
218
215
  wait_command_loop tc
219
216
 
220
217
  when :load
@@ -257,7 +254,7 @@ module DEBUGGER__
257
254
  end
258
255
 
259
256
  when :result
260
- raise "[BUG] not in subsession" unless @subsession
257
+ raise "[BUG] not in subsession" if @subsession_stack.empty?
261
258
 
262
259
  case ev_args.first
263
260
  when :try_display
@@ -369,7 +366,7 @@ module DEBUGGER__
369
366
  @ui.puts "(rdbg:#{@preset_command.source}) #{line}"
370
367
  end
371
368
  else
372
- @ui.puts "INTERNAL_INFO: #{JSON.generate(@internal_info)}" if ENV['RUBY_DEBUG_TEST_MODE']
369
+ @ui.puts "INTERNAL_INFO: #{JSON.generate(@internal_info)}" if ENV['RUBY_DEBUG_TEST_UI'] == 'terminal'
373
370
  line = @ui.readline prompt
374
371
  end
375
372
 
@@ -510,8 +507,8 @@ module DEBUGGER__
510
507
  # * break and run `<command>` before stopping.
511
508
  # * `b[reak] ... do: <command>`
512
509
  # * break and run `<command>`, and continue.
513
- # * `b[reak] ... path: <path_regexp>`
514
- # * break if the triggering event's path matches <path_regexp>.
510
+ # * `b[reak] ... path: <path>`
511
+ # * break if the path matches to `<path>`. `<path>` can be a regexp with `/regexp/`.
515
512
  # * `b[reak] if: <expr>`
516
513
  # * break if: `<expr>` is true at any lines.
517
514
  # * Note that this feature is super slow.
@@ -566,8 +563,8 @@ module DEBUGGER__
566
563
  # * runs `<command>` before stopping.
567
564
  # * `catch ... do: <command>`
568
565
  # * stops and run `<command>`, and continue.
569
- # * `catch ... path: <path_regexp>`
570
- # * stops if the exception is raised from a path that matches <path_regexp>.
566
+ # * `catch ... path: <path>`
567
+ # * stops if the exception is raised from a `<path>`. `<path>` can be a regexp with `/regexp/`.
571
568
  when 'catch'
572
569
  check_postmortem
573
570
 
@@ -588,8 +585,8 @@ module DEBUGGER__
588
585
  # * runs `<command>` before stopping.
589
586
  # * `watch ... do: <command>`
590
587
  # * stops and run `<command>`, and continue.
591
- # * `watch ... path: <path_regexp>`
592
- # * stops if the triggering event's path matches <path_regexp>.
588
+ # * `watch ... path: <path>`
589
+ # * stops if the path matches `<path>`. `<path>` can be a regexp with `/regexp/`.
593
590
  when 'wat', 'watch'
594
591
  check_postmortem
595
592
 
@@ -699,8 +696,8 @@ module DEBUGGER__
699
696
  # * Show information about accessible constants except toplevel constants.
700
697
  # * `i[nfo] g[lobal[s]]`
701
698
  # * Show information about global variables
702
- # * `i[nfo] ... </pattern/>`
703
- # * Filter the output with `</pattern/>`.
699
+ # * `i[nfo] ... /regexp/`
700
+ # * Filter the output with `/regexp/`.
704
701
  # * `i[nfo] th[read[s]]`
705
702
  # * Show all threads (same as `th[read]`).
706
703
  when 'i', 'info'
@@ -834,8 +831,8 @@ module DEBUGGER__
834
831
  # * Add an exception tracer. It indicates raising exceptions.
835
832
  # * `trace object <expr>`
836
833
  # * Add an object tracer. It indicates that an object by `<expr>` is passed as a parameter or a receiver on method call.
837
- # * `trace ... </pattern/>`
838
- # * Indicates only matched events to `</pattern/>` (RegExp).
834
+ # * `trace ... /regexp/`
835
+ # * Indicates only matched events to `/regexp/`.
839
836
  # * `trace ... into: <file>`
840
837
  # * Save trace information into: `<file>`.
841
838
  # * `trace off <num>`
@@ -978,7 +975,7 @@ module DEBUGGER__
978
975
  when 'open'
979
976
  case arg&.downcase
980
977
  when '', nil
981
- repl_open_unix
978
+ repl_open
982
979
  when 'vscode'
983
980
  repl_open_vscode
984
981
  when /\A(.+):(\d+)\z/
@@ -1003,11 +1000,7 @@ module DEBUGGER__
1003
1000
  # * `h[elp] <command>`
1004
1001
  # * Show help for the given command.
1005
1002
  when 'h', 'help', '?'
1006
- if arg
1007
- show_help arg
1008
- else
1009
- @ui.puts DEBUGGER__.help
1010
- end
1003
+ show_help arg
1011
1004
  return :retry
1012
1005
 
1013
1006
  ### END
@@ -1055,14 +1048,14 @@ module DEBUGGER__
1055
1048
  repl_open_setup
1056
1049
  end
1057
1050
 
1058
- def repl_open_unix
1059
- DEBUGGER__.open_unix nonstop: true
1051
+ def repl_open
1052
+ DEBUGGER__.open nonstop: true
1060
1053
  repl_open_setup
1061
1054
  end
1062
1055
 
1063
1056
  def repl_open_vscode
1064
1057
  CONFIG[:open_frontend] = 'vscode'
1065
- repl_open_unix
1058
+ repl_open
1066
1059
  end
1067
1060
 
1068
1061
  def step_command type, arg
@@ -1159,16 +1152,50 @@ module DEBUGGER__
1159
1152
  end
1160
1153
  end
1161
1154
 
1162
- def show_help arg
1163
- DEBUGGER__.helps.each{|cat, cs|
1164
- cs.each{|ws, desc|
1165
- if ws.include? arg
1166
- @ui.puts desc
1167
- return
1155
+ def show_help arg = nil
1156
+ instructions = (DEBUGGER__.commands.keys + DEBUGGER__.commands.values).uniq
1157
+ print_instructions = proc do |desc|
1158
+ desc.split("\n").each do |line|
1159
+ next if line.start_with?(" ") # workaround for step back
1160
+ formatted_line = line.gsub(/[\[\]\*]/, "").strip
1161
+ instructions.each do |inst|
1162
+ if formatted_line.start_with?("`#{inst}")
1163
+ desc.sub!(line, colorize(line, [:CYAN, :BOLD]))
1164
+ end
1165
+ end
1166
+ end
1167
+ @ui.puts desc
1168
+ end
1169
+
1170
+ print_category = proc do |cat|
1171
+ @ui.puts "\n"
1172
+ @ui.puts colorize("### #{cat}", [:GREEN, :BOLD])
1173
+ @ui.puts "\n"
1174
+ end
1175
+
1176
+ DEBUGGER__.helps.each { |cat, cs|
1177
+ # categories
1178
+ if arg.nil?
1179
+ print_category.call(cat)
1180
+ else
1181
+ cs.each { |ws, _|
1182
+ if ws.include?(arg)
1183
+ print_category.call(cat)
1184
+ break
1185
+ end
1186
+ }
1187
+ end
1188
+
1189
+ # instructions
1190
+ cs.each { |ws, desc|
1191
+ if arg.nil? || ws.include?(arg)
1192
+ print_instructions.call(desc.dup)
1193
+ return if arg
1168
1194
  end
1169
1195
  }
1170
1196
  }
1171
- @ui.puts "not found: #{arg}"
1197
+
1198
+ @ui.puts "not found: #{arg}" if arg
1172
1199
  end
1173
1200
 
1174
1201
  def ask msg, default = 'Y'
@@ -1272,14 +1299,20 @@ module DEBUGGER__
1272
1299
  end
1273
1300
  }
1274
1301
  expr.default_proc = nil
1275
- expr.transform_values{|v| v.join(' ')}
1302
+ expr = expr.transform_values{|v| v.join(' ')}
1303
+
1304
+ if (path = expr[:path]) && path =~ /\A\/(.*)\/\z/
1305
+ expr[:path] = Regexp.compile($1)
1306
+ end
1307
+
1308
+ expr
1276
1309
  end
1277
1310
 
1278
1311
  def repl_add_breakpoint arg
1279
1312
  expr = parse_break arg.strip
1280
1313
  cond = expr[:if]
1281
1314
  cmd = ['break', expr[:pre], expr[:do]] if expr[:pre] || expr[:do]
1282
- path = Regexp.compile(expr[:path]) if expr[:path]
1315
+ path = expr[:path]
1283
1316
 
1284
1317
  case expr[:sig]
1285
1318
  when /\A(\d+)\z/
@@ -1290,7 +1323,7 @@ module DEBUGGER__
1290
1323
  @tc << [:breakpoint, :method, $1, $2, $3, cond, cmd, path]
1291
1324
  return :noretry
1292
1325
  when nil
1293
- add_check_breakpoint cond, path
1326
+ add_check_breakpoint cond, path, cmd
1294
1327
  else
1295
1328
  @ui.puts "Unknown breakpoint format: #{arg}"
1296
1329
  @ui.puts
@@ -1302,7 +1335,7 @@ module DEBUGGER__
1302
1335
  expr = parse_break arg.strip
1303
1336
  cond = expr[:if]
1304
1337
  cmd = ['catch', expr[:pre], expr[:do]] if expr[:pre] || expr[:do]
1305
- path = Regexp.compile(expr[:path]) if expr[:path]
1338
+ path = expr[:path]
1306
1339
 
1307
1340
  bp = CatchBreakpoint.new(expr[:sig], cond: cond, command: cmd, path: path)
1308
1341
  add_bp bp
@@ -1322,8 +1355,8 @@ module DEBUGGER__
1322
1355
  add_bp bp
1323
1356
  end
1324
1357
 
1325
- def add_check_breakpoint expr, path
1326
- bp = CheckBreakpoint.new(expr, path)
1358
+ def add_check_breakpoint cond, path, command
1359
+ bp = CheckBreakpoint.new(cond: cond, path: path, command: command)
1327
1360
  add_bp bp
1328
1361
  end
1329
1362
 
@@ -1336,6 +1369,15 @@ module DEBUGGER__
1336
1369
  @ui.puts e.message
1337
1370
  end
1338
1371
 
1372
+ def clear_line_breakpoints path
1373
+ path = resolve_path(path)
1374
+ @bps.delete_if do |k, bp|
1375
+ if (Array === k) && DEBUGGER__.compare_path(k.first, path)
1376
+ bp.delete
1377
+ end
1378
+ end
1379
+ end
1380
+
1339
1381
  def add_iseq_breakpoint iseq, **kw
1340
1382
  bp = ISeqBreakpoint.new(iseq, [:line], **kw)
1341
1383
  add_bp bp
@@ -1503,27 +1545,38 @@ module DEBUGGER__
1503
1545
  end
1504
1546
 
1505
1547
  private def enter_subsession
1506
- raise "already in subsession" if @subsession
1507
- @subsession = true
1508
- stop_all_threads
1509
- @process_group.lock
1510
- DEBUGGER__.info "enter_subsession"
1548
+ if !@subsession_stack.empty?
1549
+ DEBUGGER__.info "Enter subsession (nested #{@subsession_stack.size})"
1550
+ else
1551
+ DEBUGGER__.info "Enter subsession"
1552
+ stop_all_threads
1553
+ @process_group.lock
1554
+ end
1555
+
1556
+ @subsession_stack << true
1511
1557
  end
1512
1558
 
1513
1559
  private def leave_subsession type
1514
- DEBUGGER__.info "leave_subsession"
1515
- @process_group.unlock
1516
- restart_all_threads
1560
+ raise '[BUG] leave_subsession: not entered' if @subsession_stack.empty?
1561
+ @subsession_stack.pop
1562
+
1563
+ if @subsession_stack.empty?
1564
+ DEBUGGER__.info "Leave subsession"
1565
+ @process_group.unlock
1566
+ restart_all_threads
1567
+ else
1568
+ DEBUGGER__.info "Leave subsession (nested #{@subsession_stack.size})"
1569
+ end
1570
+
1517
1571
  @tc << type if type
1518
1572
  @tc = nil
1519
- @subsession = false
1520
1573
  rescue Exception => e
1521
- STDERR.puts [e, e.backtrace].inspect
1574
+ STDERR.puts PP.pp([e, e.backtrace], ''.dup)
1522
1575
  raise
1523
1576
  end
1524
1577
 
1525
1578
  def in_subsession?
1526
- @subsession
1579
+ !@subsession_stack.empty?
1527
1580
  end
1528
1581
 
1529
1582
  ## event
@@ -1537,7 +1590,7 @@ module DEBUGGER__
1537
1590
  end
1538
1591
 
1539
1592
  pending_line_breakpoints.each do |_key, bp|
1540
- if bp.path == (iseq.absolute_path || iseq.path)
1593
+ if DEBUGGER__.compare_path(bp.path, (iseq.absolute_path || iseq.path))
1541
1594
  bp.try_activate
1542
1595
  end
1543
1596
  end
@@ -1860,6 +1913,9 @@ module DEBUGGER__
1860
1913
  puts "\nStop by #{args.first}"
1861
1914
  end
1862
1915
  end
1916
+
1917
+ def flush
1918
+ end
1863
1919
  end
1864
1920
 
1865
1921
  # manual configuration methods
@@ -1876,7 +1932,7 @@ module DEBUGGER__
1876
1932
  # nil for -r
1877
1933
  def self.require_location
1878
1934
  locs = caller_locations
1879
- dir_prefix = /#{__dir__}/
1935
+ dir_prefix = /#{Regexp.escape(__dir__)}/
1880
1936
 
1881
1937
  locs.each do |loc|
1882
1938
  case loc.absolute_path
@@ -1896,7 +1952,7 @@ module DEBUGGER__
1896
1952
 
1897
1953
  unless defined? SESSION
1898
1954
  require_relative 'local'
1899
- initialize_session UI_LocalConsole.new
1955
+ initialize_session{ UI_LocalConsole.new }
1900
1956
  end
1901
1957
 
1902
1958
  setup_initial_suspend unless nonstop
@@ -1904,8 +1960,9 @@ module DEBUGGER__
1904
1960
 
1905
1961
  def self.open host: nil, port: CONFIG[:port], sock_path: nil, sock_dir: nil, nonstop: false, **kw
1906
1962
  CONFIG.set_config(**kw)
1963
+ require_relative 'server'
1907
1964
 
1908
- if port || CONFIG[:open_frontend] == 'chrome'
1965
+ if port || CONFIG[:open_frontend] == 'chrome' || (!::Addrinfo.respond_to?(:unix))
1909
1966
  open_tcp host: host, port: (port || 0), nonstop: nonstop
1910
1967
  else
1911
1968
  open_unix sock_path: sock_path, sock_dir: sock_dir, nonstop: nonstop
@@ -1919,7 +1976,7 @@ module DEBUGGER__
1919
1976
  if defined? SESSION
1920
1977
  SESSION.reset_ui UI_TcpServer.new(host: host, port: port)
1921
1978
  else
1922
- initialize_session UI_TcpServer.new(host: host, port: port)
1979
+ initialize_session{ UI_TcpServer.new(host: host, port: port) }
1923
1980
  end
1924
1981
 
1925
1982
  setup_initial_suspend unless nonstop
@@ -1932,7 +1989,7 @@ module DEBUGGER__
1932
1989
  if defined? SESSION
1933
1990
  SESSION.reset_ui UI_UnixDomainServer.new(sock_dir: sock_dir, sock_path: sock_path)
1934
1991
  else
1935
- initialize_session UI_UnixDomainServer.new(sock_dir: sock_dir, sock_path: sock_path)
1992
+ initialize_session{ UI_UnixDomainServer.new(sock_dir: sock_dir, sock_path: sock_path) }
1936
1993
  end
1937
1994
 
1938
1995
  setup_initial_suspend unless nonstop
@@ -1959,9 +2016,10 @@ module DEBUGGER__
1959
2016
  end
1960
2017
 
1961
2018
  class << self
1962
- define_method :initialize_session do |ui|
2019
+ define_method :initialize_session do |&init_ui|
1963
2020
  DEBUGGER__.info "Session start (pid: #{Process.pid})"
1964
- ::DEBUGGER__.const_set(:SESSION, Session.new(ui))
2021
+ ::DEBUGGER__.const_set(:SESSION, Session.new)
2022
+ SESSION.activate init_ui.call
1965
2023
  load_rc
1966
2024
  end
1967
2025
  end
@@ -2062,10 +2120,64 @@ module DEBUGGER__
2062
2120
  yield
2063
2121
  end
2064
2122
 
2123
+ if File.identical?(__FILE__.upcase, __FILE__.downcase)
2124
+ # For case insensitive file system (like Windows)
2125
+ # Note that this check is not enough because case sensitive/insensitive is
2126
+ # depend on the file system. So this check is only roughly estimation.
2127
+
2128
+ def self.compare_path(a, b)
2129
+ a.downcase == b.downcase
2130
+ end
2131
+ else
2132
+ def self.compare_path(a, b)
2133
+ a == b
2134
+ end
2135
+ end
2136
+
2065
2137
  module ForkInterceptor
2066
- def fork(&given_block)
2067
- return super unless defined?(SESSION) && SESSION.active?
2138
+ if Process.respond_to? :_fork
2139
+ def _fork
2140
+ return yield unless defined?(SESSION) && SESSION.active?
2141
+
2142
+ parent_hook, child_hook = __fork_setup_for_debugger
2143
+
2144
+ super.tap do |pid|
2145
+ if pid != 0
2146
+ # after fork: parent
2147
+ parent_hook.call pid
2148
+ else
2149
+ # after fork: child
2150
+ child_hook.call
2151
+ end
2152
+ end
2153
+ end
2154
+ else
2155
+ def fork(&given_block)
2156
+ return yield unless defined?(SESSION) && SESSION.active?
2157
+ parent_hook, child_hook = __fork_setup_for_debugger
2158
+
2159
+ if given_block
2160
+ new_block = proc {
2161
+ # after fork: child
2162
+ child_hook.call
2163
+ given_block.call
2164
+ }
2165
+ super(&new_block).tap{|pid| parent_hook.call(pid)}
2166
+ else
2167
+ super.tap do |pid|
2168
+ if pid
2169
+ # after fork: parent
2170
+ parent_hook.call pid
2171
+ else
2172
+ # after fork: child
2173
+ child_hook.call
2174
+ end
2175
+ end
2176
+ end
2177
+ end
2178
+ end
2068
2179
 
2180
+ private def __fork_setup_for_debugger
2069
2181
  unless fork_mode = CONFIG[:fork_mode]
2070
2182
  if CONFIG[:parent_on_fork]
2071
2183
  fork_mode = :parent
@@ -2112,26 +2224,7 @@ module DEBUGGER__
2112
2224
  }
2113
2225
  end
2114
2226
 
2115
- if given_block
2116
- new_block = proc {
2117
- # after fork: child
2118
- child_hook.call
2119
- given_block.call
2120
- }
2121
- pid = super(&new_block)
2122
- parent_hook.call(pid)
2123
- pid
2124
- else
2125
- if pid = super
2126
- # after fork: parent
2127
- parent_hook.call pid
2128
- else
2129
- # after fork: child
2130
- child_hook.call
2131
- end
2132
-
2133
- pid
2134
- end
2227
+ return parent_hook, child_hook
2135
2228
  end
2136
2229
  end
2137
2230
 
@@ -2148,28 +2241,46 @@ module DEBUGGER__
2148
2241
  end
2149
2242
  end
2150
2243
 
2151
- if RUBY_VERSION >= '3.0.0'
2244
+ if Process.respond_to? :_fork
2245
+ module ::Process
2246
+ class << self
2247
+ prepend ForkInterceptor
2248
+ end
2249
+ end
2250
+
2251
+ # trap
2152
2252
  module ::Kernel
2153
- prepend ForkInterceptor
2154
2253
  prepend TrapInterceptor
2155
2254
  end
2255
+ module ::Signal
2256
+ class << self
2257
+ prepend TrapInterceptor
2258
+ end
2259
+ end
2156
2260
  else
2157
- class ::Object
2158
- include ForkInterceptor
2159
- include TrapInterceptor
2261
+ if RUBY_VERSION >= '3.0.0'
2262
+ module ::Kernel
2263
+ prepend ForkInterceptor
2264
+ prepend TrapInterceptor
2265
+ end
2266
+ else
2267
+ class ::Object
2268
+ include ForkInterceptor
2269
+ include TrapInterceptor
2270
+ end
2160
2271
  end
2161
- end
2162
2272
 
2163
- module ::Kernel
2164
- class << self
2165
- prepend ForkInterceptor
2166
- prepend TrapInterceptor
2273
+ module ::Kernel
2274
+ class << self
2275
+ prepend ForkInterceptor
2276
+ prepend TrapInterceptor
2277
+ end
2167
2278
  end
2168
- end
2169
2279
 
2170
- module ::Process
2171
- class << self
2172
- prepend ForkInterceptor
2280
+ module ::Process
2281
+ class << self
2282
+ prepend ForkInterceptor
2283
+ end
2173
2284
  end
2174
2285
  end
2175
2286