Skip to content

Commit 7572378

Browse files
committed
add break_on_exception option in launch
By default set to true but can be turned off if desired.
1 parent eb36dc8 commit 7572378

File tree

3 files changed

+143
-117
lines changed

3 files changed

+143
-117
lines changed

doc/osv.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ launch({opts}) *osv.launch()*
115115
the debuggee (default is true). Note: This is
116116
implemented via |:redir| internally. See
117117
|:redir| for caveats.
118+
`break_on_exception`
119+
(bool) If true, osv will break if an
120+
error/exception is encountered in the debuggee.
121+
(default is true)
118122
`profiler` (bool) Enable the internal profiler. Use
119123
|osv.print_profiler()| to see the results.
120124

lua/osv/init.lua

Lines changed: 115 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
local running = true
33

44
local builtin_debug_traceback
5+
local break_on_exception
56

67
local exception_error_msg = nil
78

@@ -164,6 +165,8 @@ function M.launch(opts)
164165
["opts.output"] = {opts.output, "b", true},
165166
["opts.profiler"] = {opts.profiler, "b", true},
166167

168+
["opts.break_on_exception"] = {opts.break_on_exception, "b", true},
169+
167170
}
168171
if opts.output ~= nil then redir_nvim_output = opts.output end
169172
end
@@ -173,6 +176,11 @@ function M.launch(opts)
173176
disable_profiler = true
174177
end
175178

179+
break_on_exception = opts and opts.break_on_exception
180+
if break_on_exception == nil then
181+
break_on_exception = true
182+
end
183+
176184

177185
if M.is_running() then
178186
vim.api.nvim_echo({{"Server is already running.", "ErrorMsg"}}, true, {})
@@ -945,135 +953,137 @@ function M.prepare_attach(blocking)
945953
end
946954

947955
local attach_now = function()
948-
if not builtin_debug_traceback then
949-
builtin_debug_traceback = debug.traceback
950-
end
951-
952-
debug.traceback = function(...)
953-
log("debug.traceback " .. vim.inspect({...}))
954-
if not M.is_running() then
955-
if builtin_debug_traceback then
956-
debug.traceback = builtin_debug_traceback
957-
return debug.traceback()
958-
end
959-
log("debug.traceback handle lost")
960-
return "one-small-step-for-vimkind lost the debug.traceback handle :("
956+
if break_on_exception then
957+
if not builtin_debug_traceback then
958+
builtin_debug_traceback = debug.traceback
961959
end
962960

963-
local off = 0
964-
local called_explicit = false
965-
local called_explicit_level = nil
966-
local sources = {}
967-
while true do
968-
local succ, info = pcall(debug.getinfo, off)
969-
if not succ or not info then
970-
break
961+
debug.traceback = function(...)
962+
log("debug.traceback " .. vim.inspect({...}))
963+
if not M.is_running() then
964+
if builtin_debug_traceback then
965+
debug.traceback = builtin_debug_traceback
966+
return debug.traceback()
967+
end
968+
log("debug.traceback handle lost")
969+
return "one-small-step-for-vimkind lost the debug.traceback handle :("
971970
end
972971

973-
log("STACK " .. (info.name or "[NO NAME]") .. " " .. (info.source or "[NO SOURCE]") .. " " .. info.currentline .. " " .. tostring(info.func == debug.traceback))
974-
sources[off] = info.source
972+
local off = 0
973+
local called_explicit = false
974+
local called_explicit_level = nil
975+
local sources = {}
976+
while true do
977+
local succ, info = pcall(debug.getinfo, off)
978+
if not succ or not info then
979+
break
980+
end
981+
982+
log("STACK " .. (info.name or "[NO NAME]") .. " " .. (info.source or "[NO SOURCE]") .. " " .. info.currentline .. " " .. tostring(info.func == debug.traceback))
983+
sources[off] = info.source
975984

976-
if info.func == debug.traceback and info.name == "traceback" then
977-
called_explicit = true
978-
called_explicit_level = off
985+
if info.func == debug.traceback and info.name == "traceback" then
986+
called_explicit = true
987+
called_explicit_level = off
988+
end
989+
off = off + 1
979990
end
980-
off = off + 1
981-
end
982991

983-
log("called explicit " .. vim.inspect(called_explicit))
984-
if called_explicit and sources[called_explicit_level+1] ~= "=[C]" then
985-
log("called explicit source " .. vim.inspect(sources[called_explicit_level+1]))
986-
return builtin_debug_traceback(...)
987-
end
992+
log("called explicit " .. vim.inspect(called_explicit))
993+
if called_explicit and sources[called_explicit_level+1] ~= "=[C]" then
994+
log("called explicit source " .. vim.inspect(sources[called_explicit_level+1]))
995+
return builtin_debug_traceback(...)
996+
end
988997

989-
local traceback_args = { ... }
990-
exception_error_msg = nil
991-
log(vim.inspect({...}))
992-
if #traceback_args > 0 then
993-
exception_error_msg = traceback_args[1]
994-
end
998+
local traceback_args = { ... }
999+
exception_error_msg = nil
1000+
log(vim.inspect({...}))
1001+
if #traceback_args > 0 then
1002+
exception_error_msg = traceback_args[1]
1003+
end
9951004

996-
local start_frame = 0
997-
local levels = 1
998-
local skip = 0
1005+
local start_frame = 0
1006+
local levels = 1
1007+
local skip = 0
9991008

1000-
local off = 0
1001-
while true do
1002-
local info = debug.getinfo(off+levels+start_frame)
1003-
if not info then
1004-
break
1005-
end
1009+
local off = 0
1010+
while true do
1011+
local info = debug.getinfo(off+levels+start_frame)
1012+
if not info then
1013+
break
1014+
end
10061015

1007-
local inside_osv = false
1008-
if info.source:sub(1, 1) == '@' and #info.source > 8 and info.source:sub(#info.source-8+1,#info.source) == "init.lua" then
1009-
local source = info.source:sub(2)
1010-
-- local path = vim.fn.resolve(vim.fn.fnamemodify(source, ":p"))
1011-
local parent = vim.fs.dirname(source)
1012-
if parent and vim.fs.basename(parent) == "osv" then
1013-
inside_osv = true
1016+
local inside_osv = false
1017+
if info.source:sub(1, 1) == '@' and #info.source > 8 and info.source:sub(#info.source-8+1,#info.source) == "init.lua" then
1018+
local source = info.source:sub(2)
1019+
-- local path = vim.fn.resolve(vim.fn.fnamemodify(source, ":p"))
1020+
local parent = vim.fs.dirname(source)
1021+
if parent and vim.fs.basename(parent) == "osv" then
1022+
inside_osv = true
1023+
end
10141024
end
1015-
end
10161025

10171026

1018-
if inside_osv then
1019-
skip = off + 1
1020-
end
1027+
if inside_osv then
1028+
skip = off + 1
1029+
end
10211030

1022-
off = off + 1
1023-
end
1031+
off = off + 1
1032+
end
10241033

10251034

1026-
exception_stacktrace = {}
1027-
while true do
1028-
local info = debug.getinfo(skip+levels+start_frame)
1029-
if not info then
1030-
break
1031-
end
1032-
local stack_desc = ""
1033-
stack_desc = (info.short_src or "") .. ":" .. (info.currentline or "")
1034-
if info.name then
1035-
stack_desc = stack_desc .. " in function " .. info.name
1036-
elseif info.what then
1037-
stack_desc = stack_desc .. " in " .. info.what .. " chunk"
1035+
exception_stacktrace = {}
1036+
while true do
1037+
local info = debug.getinfo(skip+levels+start_frame)
1038+
if not info then
1039+
break
1040+
end
1041+
local stack_desc = ""
1042+
stack_desc = (info.short_src or "") .. ":" .. (info.currentline or "")
1043+
if info.name then
1044+
stack_desc = stack_desc .. " in function " .. info.name
1045+
elseif info.what then
1046+
stack_desc = stack_desc .. " in " .. info.what .. " chunk"
1047+
end
1048+
table.insert(exception_stacktrace, stack_desc)
1049+
levels = levels + 1
10381050
end
1039-
table.insert(exception_stacktrace, stack_desc)
1040-
levels = levels + 1
1041-
end
10421051

1043-
exception_stacktrace = table.concat(exception_stacktrace, "\n")
1044-
local msg = make_event("stopped")
1045-
msg.body = {
1046-
reason = "exception",
1047-
threadId = 1,
1048-
text = exception_error_msg
1049-
}
1050-
sendProxyDAP(msg)
1052+
exception_stacktrace = table.concat(exception_stacktrace, "\n")
1053+
local msg = make_event("stopped")
1054+
msg.body = {
1055+
reason = "exception",
1056+
threadId = 1,
1057+
text = exception_error_msg
1058+
}
1059+
sendProxyDAP(msg)
10511060

1052-
running = false
1053-
while not running do
1054-
if M.stop_freeze then
1055-
M.stop_freeze = false
1056-
break
1057-
end
1058-
local i = 1
1059-
while i <= #M.server_messages do
1060-
local msg = M.server_messages[i]
1061-
local f = handlers[msg.command]
1062-
log(vim.inspect(msg))
1063-
if f then
1064-
f(msg)
1065-
else
1066-
log("Could not handle " .. msg.command)
1061+
running = false
1062+
while not running do
1063+
if M.stop_freeze then
1064+
M.stop_freeze = false
1065+
break
1066+
end
1067+
local i = 1
1068+
while i <= #M.server_messages do
1069+
local msg = M.server_messages[i]
1070+
local f = handlers[msg.command]
1071+
log(vim.inspect(msg))
1072+
if f then
1073+
f(msg)
1074+
else
1075+
log("Could not handle " .. msg.command)
1076+
end
1077+
i = i + 1
10671078
end
1068-
i = i + 1
1069-
end
10701079

1071-
M.server_messages = {}
1080+
M.server_messages = {}
10721081

1073-
vim.wait(0)
1074-
end
1082+
vim.wait(0)
1083+
end
10751084

1076-
return builtin_debug_traceback(...)
1085+
return builtin_debug_traceback(...)
1086+
end
10771087
end
10781088

10791089
debug.sethook(function(event, line)

src/exception_handler.lua.t2

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,33 @@
11
;;; lua-debug
22
;; script variables
33
local builtin_debug_traceback
4+
local break_on_exception
45

5-
;; redefine debug traceback
6-
if not builtin_debug_traceback then
7-
builtin_debug_traceback = debug.traceback
6+
;; validate launch options
7+
["opts.break_on_exception"] = {opts.break_on_exception, "b", true},
8+
9+
;; use launch options
10+
break_on_exception = opts and opts.break_on_exception
11+
if break_on_exception == nil then
12+
break_on_exception = true
813
end
914

10-
debug.traceback = function(...)
11-
log("debug.traceback " .. vim.inspect({...}))
12-
; if osv is not running bail out
13-
; if traceback was called explicitly return builtin
14-
; save error message
15-
; save error stacktrace
16-
; send exception stopped event
17-
; freeze neovim instance
18-
return builtin_debug_traceback(...)
15+
;; redefine debug traceback
16+
if break_on_exception then
17+
if not builtin_debug_traceback then
18+
builtin_debug_traceback = debug.traceback
19+
end
20+
21+
debug.traceback = function(...)
22+
log("debug.traceback " .. vim.inspect({...}))
23+
; if osv is not running bail out
24+
; if traceback was called explicitly return builtin
25+
; save error message
26+
; save error stacktrace
27+
; send exception stopped event
28+
; freeze neovim instance
29+
return builtin_debug_traceback(...)
30+
end
1931
end
2032

2133
;; restore debug traceback

0 commit comments

Comments
 (0)