Skip to content

Commit 9d2a5c0

Browse files
committed
restart all threads on eval
When a thread keeps a lock, and REPL runs a code which needs the lock, other threads should make a progress to release the lock. fix #877
1 parent e706193 commit 9d2a5c0

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

lib/debug/session.rb

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ def process_event evt
343343
opt = ev_args[3]
344344
add_tracer ObjectTracer.new(@ui, obj_id, obj_inspect, **opt)
345345
else
346-
# ignore
346+
stop_all_threads
347347
end
348348

349349
wait_command_loop
@@ -900,13 +900,13 @@ def register_default_command
900900
# * `p <expr>`
901901
# * Evaluate like `p <expr>` on the current frame.
902902
register_command 'p' do |arg|
903-
request_tc [:eval, :p, arg.to_s]
903+
request_eval :p, arg.to_s
904904
end
905905

906906
# * `pp <expr>`
907907
# * Evaluate like `pp <expr>` on the current frame.
908908
register_command 'pp' do |arg|
909-
request_tc [:eval, :pp, arg.to_s]
909+
request_eval :pp, arg.to_s
910910
end
911911

912912
# * `eval <expr>`
@@ -917,7 +917,7 @@ def register_default_command
917917
@ui.puts "\nTo evaluate the variable `#{cmd}`, use `pp #{cmd}` instead."
918918
:retry
919919
else
920-
request_tc [:eval, :call, arg]
920+
request_eval :call, arg
921921
end
922922
end
923923

@@ -928,7 +928,7 @@ def register_default_command
928928
@ui.puts "not supported on the remote console."
929929
:retry
930930
end
931-
request_tc [:eval, :irb]
931+
request_eval :irb, nil
932932
end
933933

934934
### Trace
@@ -1148,7 +1148,7 @@ def process_command line
11481148
@repl_prev_line = nil
11491149
check_unsafe
11501150

1151-
request_tc [:eval, :pp, line]
1151+
request_eval :pp, line
11521152
end
11531153

11541154
rescue Interrupt
@@ -1164,6 +1164,11 @@ def process_command line
11641164
return :retry
11651165
end
11661166

1167+
def request_eval type, src
1168+
restart_all_threads
1169+
request_tc [:eval, type, src]
1170+
end
1171+
11671172
def step_command type, arg
11681173
if type == :until
11691174
leave_subsession [:step, type, arg]

lib/debug/thread_client.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1230,7 +1230,15 @@ def wait_next_action_
12301230
rescue SuspendReplay, SystemExit, Interrupt
12311231
raise
12321232
rescue Exception => e
1233-
pp ["DEBUGGER Exception: #{__FILE__}:#{__LINE__}", e, e.backtrace]
1233+
STDERR.puts e.cause.inspect
1234+
STDERR.puts e.inspect
1235+
Thread.list.each{|th|
1236+
STDERR.puts "@@@ #{th}"
1237+
th.backtrace.each{|b|
1238+
STDERR.puts " > #{b}"
1239+
}
1240+
}
1241+
p ["DEBUGGER Exception: #{__FILE__}:#{__LINE__}", e, e.backtrace]
12341242
raise
12351243
ensure
12361244
@returning = false

test/console/eval_test.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,30 @@ def test_eval_evaluates_computation_and_assignment
3535
end
3636
end
3737
end
38+
39+
class EvalThreadTest < ConsoleTestCase
40+
def program
41+
<<~RUBY
42+
1| th0 = Thread.new{sleep}
43+
2| m = Mutex.new; q = Queue.new
44+
3| th1 = Thread.new do
45+
4| m.lock; q << true
46+
5| sleep 1
47+
6| m.unlock
48+
7| end
49+
8| q.pop # wait for locking
50+
9| p :ok
51+
RUBY
52+
end
53+
54+
def test_eval_with_threads
55+
debug_code program do
56+
type 'b 9'
57+
type 'c'
58+
type 'm.lock.nil?'
59+
assert_line_text 'false'
60+
type 'c'
61+
end
62+
end
63+
end
3864
end

0 commit comments

Comments
 (0)