rbx-trepanning 0.1.0-universal-rubinius-1.2 → 0.2.1-universal-rubinius-1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +3 -0
  3. data/.travis.yml +4 -0
  4. data/ChangeLog +162 -0
  5. data/Gemfile +16 -0
  6. data/NEWS +15 -8
  7. data/README.md +72 -0
  8. data/Rakefile +16 -13
  9. data/app/client.rb +15 -4
  10. data/app/cmd_parse.kpeg +38 -40
  11. data/app/cmd_parse.rb +25 -20
  12. data/app/cmd_parser.rb +1030 -1036
  13. data/app/complete.rb +12 -12
  14. data/app/default.rb +6 -5
  15. data/app/display.rb +2 -2
  16. data/app/frame.rb +17 -4
  17. data/app/method.rb +11 -10
  18. data/app/options.rb +21 -22
  19. data/app/util.rb +17 -10
  20. data/interface/user.rb +2 -2
  21. data/io/input.rb +13 -3
  22. data/lib/trepanning.rb +22 -23
  23. data/processor.rb +32 -32
  24. data/processor/command.rb +32 -13
  25. data/processor/command/backtrace.rb +2 -16
  26. data/processor/command/base/submgr.rb +22 -14
  27. data/processor/command/base/subsubcmd.rb +11 -13
  28. data/processor/command/base/subsubmgr.rb +38 -19
  29. data/processor/command/disassemble.rb +11 -11
  30. data/processor/command/help.rb +24 -24
  31. data/processor/command/shell.rb +17 -17
  32. data/processor/default.rb +5 -2
  33. data/processor/frame.rb +37 -0
  34. data/processor/help.rb +9 -11
  35. data/processor/load_cmds.rb +53 -40
  36. data/processor/location.rb +2 -2
  37. data/processor/mock.rb +8 -9
  38. data/processor/subcmd.rb +12 -12
  39. data/rbx-trepanning.gemspec +4 -3
  40. data/sample/rocky-trepanx-colors.rb +1 -1
  41. data/test/example/factorial.rb +10 -0
  42. data/test/functional/fn_helper.rb +8 -7
  43. data/test/functional/test-break.rb +39 -5
  44. data/test/functional/test-recursive-bt.rb +105 -0
  45. data/test/integration/helper.rb +14 -14
  46. data/test/integration/test-quit.rb +8 -2
  47. data/test/unit/cmd-helper.rb +2 -2
  48. data/test/unit/test-base-subcmd.rb +14 -3
  49. data/test/unit/test-completion.rb +7 -3
  50. data/test/unit/test-io-tcpserver.rb +10 -5
  51. data/test/unit/test-proc-validate.rb +4 -4
  52. metadata +208 -113
  53. data/README.textile +0 -34
data/app/complete.rb CHANGED
@@ -12,21 +12,21 @@ class Trepan
12
12
  def complete_token(complete_ary, prefix)
13
13
  complete_ary.select { |cmd| cmd.to_s.start_with?(prefix) }.map{|cmd| cmd.to_s}.sort
14
14
  end
15
-
15
+
16
16
  def complete_token_with_next(complete_hash, prefix, cmd_prefix='')
17
17
  result = []
18
- complete_hash.each do |cmd_name, cmd_obj|
19
- result << [cmd_name.to_s[cmd_prefix.size..-1], cmd_obj] if
18
+ complete_hash.each do |cmd_name, cmd_obj|
19
+ result << [cmd_name.to_s[cmd_prefix.size..-1], cmd_obj] if
20
20
  cmd_name.to_s.start_with?(cmd_prefix + prefix)
21
21
  end
22
22
  result.sort{|a, b| a[0] <=> b[0]}
23
23
  end
24
-
24
+
25
25
  # Find all starting matches in Hash +aliases+ that start with +prefix+,
26
26
  # but filter out any matches already in +expanded+.
27
27
  def complete_token_filtered(aliases, prefix, expanded)
28
28
  complete_ary = aliases.keys
29
- complete_ary.select { |cmd|
29
+ complete_ary.select { |cmd|
30
30
  cmd.to_s.start_with?(prefix) && ! expanded.member?(aliases[cmd])}.sort
31
31
  end
32
32
 
@@ -37,31 +37,31 @@ class Trepan
37
37
  complete_ary = aliases.keys
38
38
  expanded_ary = expanded.keys
39
39
  result = []
40
- complete_ary.each do |cmd|
41
- if cmd.to_s.start_with?(prefix) &&
40
+ complete_ary.each do |cmd|
41
+ if cmd.to_s.start_with?(prefix) &&
42
42
  !expanded_ary.member?(aliases[cmd])
43
- result << [cmd, commands[aliases[cmd]]]
43
+ result << [cmd, commands[aliases[cmd]]]
44
44
  end
45
45
  end
46
46
  result
47
47
  end
48
48
 
49
49
  # Find the next token in str string from start_pos, we return
50
- # the token and the next blank position after the token or
50
+ # the token and the next blank position after the token or
51
51
  # str.size if this is the last token. Tokens are delimited by
52
52
  # white space.
53
53
  def next_token(str, start_pos)
54
54
  look_at = str[start_pos..-1]
55
55
  next_nonblank_pos = start_pos + (look_at =~ /\S/ || 0)
56
- next_blank_pos =
56
+ next_blank_pos =
57
57
  if next_match = str[next_nonblank_pos..-1] =~ /\s/
58
- next_nonblank_pos + next_match
58
+ next_nonblank_pos + next_match
59
59
  else
60
60
  str.size
61
61
  end
62
62
  return [next_blank_pos, str[next_nonblank_pos...next_blank_pos]]
63
63
  end
64
-
64
+
65
65
  end
66
66
  end
67
67
 
data/app/default.rb CHANGED
@@ -9,7 +9,7 @@ class Trepan
9
9
  DEFAULT_SETTINGS = {
10
10
  :cmdproc_opts => {}, # Default Trepan::CmdProcessor settings
11
11
  :core_opts => {}, # Default Trepan::Core settings
12
- :delete_restore => true, # Delete restore profile after reading?
12
+ :delete_restore => true, # Delete restore profile after reading?
13
13
  :initial_dir => nil, # If --cd option was given, we save it here.
14
14
  :nx => false, # Don't run user startup file (e.g. .trepanxrc)
15
15
  :offset => 0, # skipping back +offset+ frames. This lets you start
@@ -18,7 +18,7 @@ class Trepan
18
18
  # Default values used only when 'server' or 'client'
19
19
  # (out-of-process debugging)
20
20
  :port => 1955,
21
- :host => 'localhost',
21
+ :host => 'localhost',
22
22
 
23
23
  :restart_argv => Rubinius::OS_ARGV,
24
24
  # Command run when "restart" is given.
@@ -27,6 +27,7 @@ class Trepan
27
27
  # command-line we need this to skip
28
28
  # over some initial Rubinius loader
29
29
  # commands.
30
+ :start_frame => 1,
30
31
  } unless defined?(DEFAULT_SETTINGS)
31
32
 
32
33
  # Default settings for Trepan run from the command line.
@@ -36,7 +37,7 @@ class Trepan
36
37
  :nx => false, # Don't run user startup file (e.g. .trepanxrc)
37
38
  :output => nil,
38
39
  :port => DEFAULT_SETTINGS[:port],
39
- :host => DEFAULT_SETTINGS[:host],
40
+ :host => DEFAULT_SETTINGS[:host],
40
41
  :server => false, # Out-of-process debugging?
41
42
  :readline => true, # Try to use GNU Readline?
42
43
  # Note that at most one of :server or :client can be true.
@@ -48,10 +49,10 @@ class Trepan
48
49
  :hide_stack => true,
49
50
  } unless defined?(DEFAULT_DEBUG_STR_SETTINGS)
50
51
 
51
- CMD_INITFILE_BASE =
52
+ CMD_INITFILE_BASE =
52
53
  if RUBY_PLATFORM =~ /mswin/
53
54
  # Of course MS Windows has to be different
54
- HOME_DIR = (ENV['HOME'] ||
55
+ HOME_DIR = (ENV['HOME'] ||
55
56
  ENV['HOMEDRIVE'].to_s + ENV['HOMEPATH'].to_s).to_s
56
57
  'trepanx.ini'
57
58
  else
data/app/display.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2010, 2011, 2013 Rocky Bernstein <rockyb@rubyforge.net>
3
3
  # Classes to support gdb-like display/undisplay.
4
4
 
5
5
  require 'rubygems'; require 'require_relative'
@@ -8,7 +8,7 @@ require_relative 'frame'
8
8
  # return suitable frame signature to key display expressions off of.
9
9
  def display_signature(frame)
10
10
  return nil unless frame
11
- frame.vm_location.static_scope
11
+ frame.vm_location.constant_scope
12
12
  end
13
13
 
14
14
  # Manage a list of display expressions.
data/app/frame.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
1
+ # Copyright (C) 2010-2011, 2013 Rocky Bernstein <rockyb@rubyforge.net>
2
2
  class Trepan
3
3
 
4
4
  # Call-Stack frame methods
@@ -18,7 +18,7 @@ class Trepan
18
18
  def binding
19
19
  @binding ||= Binding.setup(@vm_location.variables,
20
20
  @vm_location.method,
21
- @vm_location.static_scope)
21
+ @vm_location.constant_scope)
22
22
  end
23
23
 
24
24
  def describe(opts = {})
@@ -80,6 +80,19 @@ class Trepan
80
80
  method.local_names
81
81
  end
82
82
 
83
+ # Return true if frame1 and frame2 are at the same place.
84
+ # We use this for example in detecting tail recursion.
85
+ def location_equal(other_frame)
86
+ # if self && other_frame
87
+ # puts(self.vm_location.line, other_frame.vm_location.line,
88
+ # self.vm_location.ip, other_frame.vm_location.ip,
89
+ # self.vm_location.method.active_path, other_frame.vm_locaion.method.actionve_path)
90
+ # end
91
+ self && other_frame && self.vm_location.line == other_frame.vm_location.line &&
92
+ self.vm_location.ip == other_frame.vm_location.ip &&
93
+ self.vm_location.method.active_path == other_frame.vm_location.method.active_path
94
+ end
95
+
83
96
  def method
84
97
  @vm_location.method
85
98
  end
@@ -93,13 +106,13 @@ class Trepan
93
106
  end
94
107
 
95
108
  def eval?
96
- static = @vm_location.static_scope
109
+ static = @vm_location.constant_scope
97
110
  static && static.script && static.script.eval_source
98
111
  end
99
112
 
100
113
  def eval_string
101
114
  return nil unless eval?
102
- static = @vm_location.static_scope
115
+ static = @vm_location.constant_scope
103
116
  static.script.eval_source
104
117
  end
105
118
 
data/app/method.rb CHANGED
@@ -1,9 +1,9 @@
1
- # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
1
+ # Copyright (C) 2010, 2013 Rocky Bernstein <rockyb@rubyforge.net>
2
2
  module Trepanning
3
3
  module Method
4
4
 
5
5
  module_function
6
- ## FIXME: until the next two routines find their way back into
6
+ ## FIXME: until the next two routines find their way back into
7
7
  ## Rubinius::CompiledMethod...
8
8
  ##
9
9
  # Locates the instruction address (IP) of the first instruction on
@@ -79,24 +79,24 @@ module Trepanning
79
79
  unless cm.kind_of?(Rubinius::CompiledMethod)
80
80
  return nil
81
81
  end
82
-
82
+
83
83
  lines = lines_of_method(cm)
84
- return cm if lines.member?(line)
84
+ return cm if lines.member?(line)
85
85
  scope = cm.scope
86
- return nil unless scope.current_script
87
- cm = scope.current_script.compiled_method
86
+ return nil unless scope and scope.current_script
87
+ cm = scope.current_script.compiled_code
88
88
  lines = lines_of_method(cm)
89
89
  until lines.member?(line) do
90
90
  child = scope
91
91
  scope = scope.parent
92
92
  unless scope
93
93
  # child is the top-most scope. Search down from here.
94
- cm = child.current_script.compiled_method
94
+ cm = child.current_script.compiled_code
95
95
  pair = locate_line(line, cm)
96
96
  ## pair = cm.locate_line(line)
97
97
  return pair ? pair[0] : nil
98
98
  end
99
- cm = scope.current_script.compiled_method
99
+ cm = scope.current_script.compiled_code
100
100
  lines = lines_of_method(cm)
101
101
  end
102
102
  return cm
@@ -104,10 +104,11 @@ module Trepanning
104
104
 
105
105
  def top_scope(cm)
106
106
  scope = cm.scope
107
+ return unless scope
107
108
  while true do
108
109
  scope = scope.parent
109
110
  break unless scope && scope.current_script
110
- cm = scope.current_script.compiled_method
111
+ cm = scope.current_script.compiled_code
111
112
  end
112
113
  cm
113
114
  end
@@ -170,7 +171,7 @@ if __FILE__ == $0
170
171
  p find_method_with_line(cm, line+2)
171
172
  puts "top scope: #{top_scope(cm)}"
172
173
  ip = locate_line( __LINE__, cm)[1]
173
- puts "Line #{__LINE__} has ip #{ip}"
174
+ puts "Line #{__LINE__} has ip #{ip}"
174
175
  [-1, 0, 10, ip, 10000].each do |i|
175
176
  puts "IP #{i} is %svalid" % (valid_ip?(cm, i) ? '' : 'not ')
176
177
  end
data/app/options.rb CHANGED
@@ -1,16 +1,15 @@
1
-
2
1
  #!/usr/bin/env ruby
3
2
  # -*- coding: utf-8 -*-
4
- # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
3
+ # Copyright (C) 2010-2011, 2013 Rocky Bernstein <rockyb@rubyforge.net>
5
4
  #=== Summary
6
- # Parses command-line options.
5
+ # Parses command-line options.
7
6
 
8
7
  require 'optparse'
9
8
  class Trepan
10
9
  require 'rubygems'; require 'require_relative'
11
10
  require_relative 'default'
12
11
 
13
- VERSION = '0.1.0'
12
+ VERSION = '0.2.1'
14
13
  PROGRAM = 'trepanx' unless defined? Trepan::PROGRAM
15
14
 
16
15
  def self.show_version
@@ -20,7 +19,7 @@ class Trepan
20
19
  def self.copy_default_options
21
20
  options = {}
22
21
  DEFAULT_CMDLINE_SETTINGS.each do |key, value|
23
- begin
22
+ begin
24
23
  options[key] = value.clone
25
24
  rescue TypeError
26
25
  options[key] = value
@@ -45,8 +44,8 @@ EOB
45
44
  options[:client] = true
46
45
  end
47
46
  end
48
- opts.on('-c', '--command FILE', String,
49
- 'Execute debugger commands from FILE') do |cmdfile|
47
+ opts.on('-c', '--command FILE', String,
48
+ 'Execute debugger commands from FILE') do |cmdfile|
50
49
  if File.readable?(cmdfile)
51
50
  options[:cmdfiles] << cmdfile
52
51
  elsif File.exists?(cmdfile)
@@ -55,7 +54,7 @@ EOB
55
54
  stderr.puts "Command file '#{cmdfile}' does not exist."
56
55
  end
57
56
  end
58
- opts.on('--cd DIR', String, 'Change current directory to DIR') do |dir|
57
+ opts.on('--cd DIR', String, 'Change current directory to DIR') do |dir|
59
58
  if File.directory?(dir)
60
59
  if File.executable?(dir)
61
60
  options[:chdir] = dir
@@ -66,24 +65,24 @@ EOB
66
65
  stderr.puts "\"#{dir}\" is not a directory. Option --cd ignored."
67
66
  end
68
67
  end
69
- opts.on('--basename',
70
- 'Show only file basename in file locations') do
68
+ opts.on('--basename',
69
+ 'Show only file basename in file locations') do
71
70
  options[:basename] = true
72
71
  end
73
- opts.on('-d', '--debug', 'Set $DEBUG=true') do
72
+ opts.on('-d', '--debug', 'Set $DEBUG=true') do
74
73
  $DEBUG = true
75
74
  end
76
75
  opts.on('--[no-]highlight',
77
76
  'Use [no] syntax highlight output') do |v|
78
77
  options[:highlight] = ((v) ? :term : nil)
79
78
  end
80
- opts.on('-h', '--host NAME', String,
81
- 'Host or IP used in TCP connections for --server or --client. ' +
82
- "Default is #{DEFAULT_SETTINGS[:host].inspect}.") do
83
- |name_or_ip|
79
+ opts.on('-h', '--host NAME', String,
80
+ 'Host or IP used in TCP connections for --server or --client. ' +
81
+ "Default is #{DEFAULT_SETTINGS[:host].inspect}.") do
82
+ |name_or_ip|
84
83
  options[:host] = name_or_ip
85
84
  end
86
- opts.on('-I', '--include PATH', String, 'Add PATH to $LOAD_PATH') do
85
+ opts.on('-I', '--include PATH', String, 'Add PATH to $LOAD_PATH') do
87
86
  |path|
88
87
  $LOAD_PATH.unshift(path)
89
88
  end
@@ -91,10 +90,10 @@ EOB
91
90
  "Do not run debugger initialization file #{CMD_INITFILE}") do
92
91
  options[:nx] = true
93
92
  end
94
- opts.on('-p', '--port NUMBER', Integer,
95
- 'Port number used in TCP connections for --server or --client. ' +
96
- "Default is #{DEFAULT_SETTINGS[:port]}.") do
97
- |num|
93
+ opts.on('-p', '--port NUMBER', Integer,
94
+ 'Port number used in TCP connections for --server or --client. ' +
95
+ "Default is #{DEFAULT_SETTINGS[:port]}.") do
96
+ |num|
98
97
  options[:port] = num
99
98
  end
100
99
  opts.on('--[no-]readline',
@@ -125,9 +124,9 @@ EOB
125
124
  opts.on_tail('-?', '--help', 'Show this message') do
126
125
  options[:help] = true
127
126
  stdout.puts opts
128
- exit
127
+ exit
129
128
  end
130
- opts.on_tail('-v', '--version',
129
+ opts.on_tail('-v', '--version',
131
130
  'print the version') do
132
131
  options[:version] = true
133
132
  stdout.puts show_version
data/app/util.rb CHANGED
@@ -1,9 +1,10 @@
1
- # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
1
+ # Copyright (C) 2010-2011, 2013 Rocky Bernstein <rockyb@rubyforge.net>
2
+ require 'redcard/rubinius'
2
3
 
3
4
  class Trepan
4
5
  module Util
5
6
 
6
- module_function
7
+ module_function
7
8
  def safe_repr(str, max, elipsis='... ')
8
9
  if str.is_a?(String) && max > 0 && str.size > max && !str.index("\n")
9
10
  "%s%s%s" % [ str[0...max/2], elipsis, str[str.size-max/2..str.size]]
@@ -16,20 +17,20 @@ class Trepan
16
17
  # If name is a unique leading prefix of one of the entries of list,
17
18
  # then return that. Otherwise return name.
18
19
  def uniq_abbrev(list, name)
19
- candidates = list.select do |try_name|
20
+ candidates = list.select do |try_name|
20
21
  try_name.start_with?(name)
21
22
  end
22
23
  candidates.size == 1 ? candidates.first : name
23
24
  end
24
25
 
25
26
  # extract the "expression" part of a line of source code.
26
- #
27
+ #
27
28
  def extract_expression(text)
28
29
  if text =~ /^\s*(?:if|elsif|unless)\s+/
29
- text.gsub!(/^\s*(?:if|elsif|unless)\s+/,'')
30
+ text.gsub!(/^\s*(?:if|elsif|unless)\s+/,'')
30
31
  text.gsub!(/\s+then\s*$/, '')
31
32
  elsif text =~ /^\s*(?:until|while)\s+/
32
- text.gsub!(/^\s*(?:until|while)\s+/,'')
33
+ text.gsub!(/^\s*(?:until|while)\s+/,'')
33
34
  text.gsub!(/\s+do\s*$/, '')
34
35
  elsif text =~ /^\s*return\s+/
35
36
  # EXPRESION in: return EXPRESSION
@@ -46,14 +47,20 @@ class Trepan
46
47
  return text
47
48
  end
48
49
 
50
+
51
+ def rubinius_internal?(loc)
52
+ ('Object#' == loc.describe_receiver &&
53
+ :__script__ == loc.name && RedCard.check('1.8')) or
54
+ ('Rubinius::Loader#' == loc.describe_receiver && RedCard.check('1.9'))
55
+ end
56
+
49
57
  # Find user portion of script skipping over Rubinius code loading.
50
58
  # Unless hidestack is off, we don't show parts of the frame below this.
51
59
  def find_main_script(locs)
52
60
  candidate = nil
53
61
  (locs.size-1).downto(0) do |i|
54
62
  loc = locs[i]
55
- if 'Object#' == loc.describe_receiver &&
56
- :__script__ == loc.name
63
+ if rubinius_internal?(loc)
57
64
  if loc.method.active_path =~ /\/trepanx$/ ||
58
65
  loc.method.active_path == 'kernel/loader.rb'
59
66
  # Might have been run from standalone trepanx.
@@ -74,7 +81,7 @@ class Trepan
74
81
  result = yield
75
82
  $VERBOSE = original_verbosity
76
83
  return result
77
- end
84
+ end
78
85
  end
79
86
  end
80
87
 
@@ -86,7 +93,7 @@ if __FILE__ == $0
86
93
  puts safe_repr(string.inspect, 17)
87
94
  puts safe_repr(string.inspect, 17, '')
88
95
  locs = Rubinius::VM.backtrace(0)
89
- locs.each_with_index do |l, i|
96
+ locs.each_with_index do |l, i|
90
97
  puts "#{i}: #{l.describe}"
91
98
  end
92
99
  ## puts "main script in above is #{locs.size() - 1 - find_main_script(locs)}"
data/interface/user.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2010-2012 Rocky Bernstein <rockyb@rubyforge.net>
3
3
 
4
4
  # Interface when communicating with the user.
5
5
 
@@ -120,7 +120,7 @@ class Trepan::UserInterface < Trepan::Interface
120
120
 
121
121
  def readline(prompt='')
122
122
  @output.flush
123
- if @input.line_edit && @opts[:readline]
123
+ if @input.line_edit && @input.use_readline
124
124
  @input.readline(prompt)
125
125
  else
126
126
  @output.write(prompt) if prompt and prompt.size > 0
data/io/input.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2010-2012 Rocky Bernstein <rockyb@rubyforge.net>
3
3
 
4
4
  # Debugger user/command-oriented input possibly attached to IO-style
5
5
  # input or GNU Readline.
@@ -14,6 +14,8 @@ class Trepan
14
14
  # input or GNU Readline.
15
15
  class UserInput < Trepan::InputBase
16
16
 
17
+ attr_reader :use_readline
18
+
17
19
  @@readline_finalized = false
18
20
 
19
21
  def initialize(inp, opts={})
@@ -37,8 +39,16 @@ class Trepan
37
39
  if @line_edit && @use_readline
38
40
  line = Readline.readline(prompt, true)
39
41
  else
40
- line = @input.gets
42
+ # Prompt should be empty and should have been
43
+ # handled by caller.
44
+ unless prompt.empty?
45
+ raise RuntimeError,
46
+ "Internal error: prompt '#{prompt}' should have been handled by caller" unless prompt.empty?
41
47
  end
48
+ line = @input.gets
49
+ end
50
+ rescue Interrupt
51
+ return ''
42
52
  rescue EOFError
43
53
  rescue => e
44
54
  puts $!.backtrace
@@ -65,7 +75,7 @@ class Trepan
65
75
  end
66
76
 
67
77
  def finalize
68
- if defined?(RbReadline) && !@@readline_finalized
78
+ if defined?(RbReadline) && !@@readline_finalized
69
79
  begin
70
80
  RbReadline.rl_cleanup_after_signal()
71
81
  rescue