debug 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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