Repository navigation
Debugger is not Fiber-safe #490
Copy link
Copy link
Closed
Description
Your environment
ruby -v: 3.1.0rdbg -v: 1.4.0
Describe the bug
If a Fiber can trigger breakpoints and is resumed during a debugging session, it'll crash the debugger due to repeatedly entering subsession: already in subsession (RuntimeError).
To Reproduce
Script:
def foo
end
f = Fiber.new do
foo
end
binding.b(pre: "b Object#foo ;; f.resume")Command:
$ exe/rdbg -e "c" target.rb
Result:
❯ exe/rdbg -e "c" target.rb
[1, 9] in target.rb
=> 1| def foo
2| end
3|
4| f = Fiber.new do
5| foo
6| end
7|
8| binding.b(pre: "b Object#foo ;; f.resume")
9|
=>#0 <main> at target.rb:1
(rdbg:commands) c
[3, 9] in target.rb
3|
4| f = Fiber.new do
5| foo
6| end
7|
=> 8| binding.b(pre: "b Object#foo ;; f.resume")
9|
=>#0 <main> at target.rb:8
(rdbg:binding.break) b Object#foo
#0 BP - Method Object#foo at target.rb:1
(rdbg:binding.break) f.resume
#<Thread:0x0000000110a725e0@DEBUGGER__::SESSION@server /Users/st0012/projects/debug/lib/debug/session.rb:147 run> terminated with exception (report_on_exception is true):
/Users/st0012/projects/debug/lib/debug/session.rb:1505:in `enter_subsession': already in subsession (RuntimeError)
from /Users/st0012/projects/debug/lib/debug/session.rb:233:in `process_event'
from /Users/st0012/projects/debug/lib/debug/session.rb:197:in `session_server_main'
from /Users/st0012/projects/debug/lib/debug/session.rb:167:in `block in activate'
["DEBUGGER Exception: /Users/st0012/projects/debug/lib/debug/thread_client.rb:994",
#<RuntimeError: already in subsession>,
["/Users/st0012/projects/debug/lib/debug/session.rb:1505:in `enter_subsession'", "/Users/st0012/projects/debug/lib/debug/session.rb:233:in `process_event'", "/Users/st0012/projects/debug/lib/debug/session.rb:197:in `session_server_main'", "/Users/st0012/projects/debug/lib/debug/session.rb:167:in `block in activate'"]]
["DEBUGGER Exception: /Users/st0012/projects/debug/lib/debug/thread_client.rb:994",
#<NoMethodError: undefined method `width' for nil:NilClass
@ui.width
^^^^^^>,
["/Users/st0012/projects/debug/lib/debug/session.rb:1588:in `width'",
"/Users/st0012/projects/debug/lib/debug/thread_client.rb:805:in `wait_next_action_'",
"/Users/st0012/projects/debug/lib/debug/thread_client.rb:684:in `wait_next_action'",
"/Users/st0012/projects/debug/lib/debug/thread_client.rb:292:in `suspend'",
"/Users/st0012/projects/debug/lib/debug/thread_client.rb:224:in `on_breakpoint'",
"/Users/st0012/projects/debug/lib/debug/breakpoint.rb:65:in `suspend'",
"/Users/st0012/projects/debug/lib/debug/breakpoint.rb:157:in `block in setup'",
"/Users/st0012/projects/debug/lib/debug/session.rb:2195:in `debugger'",
"target.rb:8:in `<main>'"]]
/Users/st0012/projects/debug/lib/debug/session.rb:1588:in `width': undefined method `width' for nil:NilClass (NoMethodError)
@ui.width
^^^^^^
from /Users/st0012/projects/debug/lib/debug/thread_client.rb:805:in `wait_next_action_'
from /Users/st0012/projects/debug/lib/debug/thread_client.rb:684:in `wait_next_action'
from /Users/st0012/projects/debug/lib/debug/thread_client.rb:292:in `suspend'
from /Users/st0012/projects/debug/lib/debug/thread_client.rb:224:in `on_breakpoint'
from /Users/st0012/projects/debug/lib/debug/breakpoint.rb:65:in `suspend'
from /Users/st0012/projects/debug/lib/debug/breakpoint.rb:157:in `block in setup'
from /Users/st0012/projects/debug/lib/debug/session.rb:2195:in `debugger'
from target.rb:8:in `<main>'
Result with debug logs (from #469)
❯ RUBY_DEBUG_LOG_LEVEL=DEBUG exe/rdbg -e "c" target.rb
DEBUGGER (INFO): Session start (pid: 69294)
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@<internal:/Users/st0012/.rbenv/versions/3.1.0/lib/ruby/3.1.0/rubygems/core_ext/kernel_require.rb>:85:in `require'> changed mode (waiting -> running)
DEBUGGER (INFO): Thread #1 is created.
DEBUGGER (DEBUG): #<DBG:TC 2:waiting@/Users/st0012/projects/debug/lib/debug/session.rb:152:in `block in activate'> changed mode (waiting -> running)
DEBUGGER (INFO): Thread #2 is created.
DEBUGGER (DEBUG): #<DBG:TC 1:running@/Users/st0012/projects/debug/lib/debug/session.rb:117:in `block in initialize'> changed mode (running -> waiting)
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@/Users/st0012/projects/debug/lib/debug/session.rb:117:in `block in initialize'> sent Event { type: :load, args: ["<RubyVM::InstructionSequence:<main>@target.rb:0>", "nil"] } to Session
DEBUGGER (INFO): Load /Users/st0012/projects/debug/target.rb
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@/Users/st0012/projects/debug/lib/debug/session.rb:117:in `block in initialize'> received Cmd { type: :continue, args: [] } from Session
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@/Users/st0012/projects/debug/lib/debug/session.rb:117:in `block in initialize'> changed mode (waiting -> running)
DEBUGGER (DEBUG): #<DBG:TC 1:running@target.rb:1:in `<main>'> was suspended for :line
DEBUGGER (DEBUG): #<DBG:TC 1:running@target.rb:1:in `<main>'> changed mode (running -> waiting)
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@target.rb:1:in `<main>'> sent Event { type: :suspend, args: [":breakpoint", "[\"/Users/st0012/projects/debug/target.rb\", 1]"] } to Session
DEBUGGER (INFO): enter_subsession
[1, 9] in target.rb
=> 1| def foo
2| end
3|
4| f = Fiber.new do
5| foo
6| end
7|
8| binding.b(pre: "b Object#foo ;; f.resume")
9|
=>#0 <main> at target.rb:1
(rdbg:commands) c
DEBUGGER (INFO): leave_subsession
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@target.rb:1:in `<main>'> received Cmd { type: :continue, args: [] } from Session
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@target.rb:1:in `<main>'> changed mode (waiting -> running)
DEBUGGER (DEBUG): #<DBG:TC 1:running@target.rb:8:in `<main>'> was suspended for :line
DEBUGGER (DEBUG): #<DBG:TC 1:running@target.rb:8:in `<main>'> changed mode (running -> waiting)
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@target.rb:8:in `<main>'> sent Event { type: :suspend, args: [":breakpoint", "[\"/Users/st0012/projects/debug/lib/debug/session.rb\", 2195]"] } to Session
DEBUGGER (INFO): enter_subsession
[3, 9] in target.rb
3|
4| f = Fiber.new do
5| foo
6| end
7|
=> 8| binding.b(pre: "b Object#foo ;; f.resume")
9|
=>#0 <main> at target.rb:8
(rdbg:binding.break) b Object#foo
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@target.rb:8:in `<main>'> received Cmd { type: :breakpoint, args: [":method", "\"Object\"", "\"#\"", "\"foo\"", "nil", "nil", "nil"] } from Session
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@target.rb:8:in `<main>'> changed mode (waiting -> running)
DEBUGGER (DEBUG): #<DBG:TC 1:running@target.rb:8:in `<main>'> sent Event { type: :result, args: [":method_breakpoint", "#<DEBUGGER__::MethodBreakpoint:0x000000010da4a908 @sig_klass_name=\"Object\", @sig_op=\"#\", @sig_method_name=\"foo\", @klass_eval_binding=nil, @override_method=false, @klass=Object, @method=#<UnboundMethod: Object#foo()
target.rb:1>, @cond=nil, @cond_class=nil, @command=nil, @path=nil, @key=\"Object#foo\", @deleted=false, @tp=#<TracePoint:line /Users/st0012/projects/debug/lib/debug/session.rb:2195 in `debugger'>>"] } to Session
DEBUGGER (DEBUG): #<DBG:TC 1:running@target.rb:8:in `<main>'> changed mode (running -> waiting)
#0 BP - Method Object#foo at target.rb:1
(rdbg:binding.break) f.resume
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@target.rb:8:in `<main>'> received Cmd { type: :eval, args: [":pp", "\"f.resume\""] } from Session
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@target.rb:8:in `<main>'> changed mode (waiting -> running)
DEBUGGER (DEBUG): #<DBG:TC 1:running@target.rb:5:in `block in <main>'> was suspended for :call
DEBUGGER (DEBUG): #<DBG:TC 1:running@target.rb:5:in `block in <main>'> changed mode (running -> waiting)
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@target.rb:5:in `block in <main>'> sent Event { type: :suspend, args: [":breakpoint", "\"Object#foo\""] } to Session
#<Thread:0x000000010d768938@DEBUGGER__::SESSION@server /Users/st0012/projects/debug/lib/debug/session.rb:147 run> terminated with exception (report_on_exception is true):
/Users/st0012/projects/debug/lib/debug/session.rb:1505:in `enter_subsession': already in subsession (RuntimeError)
from /Users/st0012/projects/debug/lib/debug/session.rb:233:in `process_event'
from /Users/st0012/projects/debug/lib/debug/session.rb:197:in `session_server_main'
from /Users/st0012/projects/debug/lib/debug/session.rb:167:in `block in activate'
DEBUGGER (DEBUG): #<DBG:TC 1:waiting@target.rb:5:in `block in <main>'> changed mode (waiting -> running)
["DEBUGGER Exception: /Users/st0012/projects/debug/lib/debug/thread_client.rb:994",
#<RuntimeError: already in subsession>,
["/Users/st0012/projects/debug/lib/debug/session.rb:1505:in `enter_subsession'", "/Users/st0012/projects/debug/lib/debug/session.rb:233:in `process_event'", "/Users/st0012/projects/debug/lib/debug/session.rb:197:in `session_server_main'", "/Users/st0012/projects/debug/lib/debug/session.rb:167:in `block in activate'"]]
["DEBUGGER Exception: /Users/st0012/projects/debug/lib/debug/thread_client.rb:994",
#<NoMethodError: undefined method `width' for nil:NilClass
@ui.width
^^^^^^>,
["/Users/st0012/projects/debug/lib/debug/session.rb:1588:in `width'",
"/Users/st0012/projects/debug/lib/debug/thread_client.rb:805:in `wait_next_action_'",
"/Users/st0012/projects/debug/lib/debug/thread_client.rb:684:in `wait_next_action'",
"/Users/st0012/projects/debug/lib/debug/thread_client.rb:292:in `suspend'",
"/Users/st0012/projects/debug/lib/debug/thread_client.rb:224:in `on_breakpoint'",
"/Users/st0012/projects/debug/lib/debug/breakpoint.rb:65:in `suspend'",
"/Users/st0012/projects/debug/lib/debug/breakpoint.rb:157:in `block in setup'",
"/Users/st0012/projects/debug/lib/debug/session.rb:2195:in `debugger'",
"target.rb:8:in `<main>'"]]
/Users/st0012/projects/debug/lib/debug/session.rb:1588:in `width': undefined method `width' for nil:NilClass (NoMethodError)
@ui.width
^^^^^^
from /Users/st0012/projects/debug/lib/debug/thread_client.rb:805:in `wait_next_action_'
from /Users/st0012/projects/debug/lib/debug/thread_client.rb:684:in `wait_next_action'
from /Users/st0012/projects/debug/lib/debug/thread_client.rb:292:in `suspend'
from /Users/st0012/projects/debug/lib/debug/thread_client.rb:224:in `on_breakpoint'
from /Users/st0012/projects/debug/lib/debug/breakpoint.rb:65:in `suspend'
from /Users/st0012/projects/debug/lib/debug/breakpoint.rb:157:in `block in setup'
from /Users/st0012/projects/debug/lib/debug/session.rb:2195:in `debugger'
from target.rb:8:in `<main>'
Expected behavior
Ideally, it should enter another debugging session (nested sessions). But it requires a large structural change. So before that happens, I hope the debugger would tell users that it needs to skip the inner session instead of crashing.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
st0012 commentedon Mar 24, 2022
This is now solved with the support of nested subsessions.
breakpoints do not work with fibers