diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index b0b684064e..b8739ff9b3 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2084,6 +2084,7 @@ ctxsize() Number return |context-stack| size cursor({lnum}, {col} [, {off}]) Number move cursor to {lnum}, {col}, {off} cursor({list}) Number move cursor to position in {list} +debugbreak({pid}) Number interrupt process being debugged deepcopy({expr} [, {noref}]) any make a full copy of {expr} delete({fname} [, {flags}]) Number delete the file or directory {fname} deletebufline({expr}, {first}[, {last}]) @@ -3641,6 +3642,11 @@ exp({expr}) *exp()* :echo exp(-1) < 0.367879 +debugbreak({pid}) *debugbreak()* + Specifically used to interrupt a program being debugged. It + will cause process {pid} to get a SIGTRAP. Behavior for other + processes is undefined. See |terminal-debugger|. + {Sends a SIGINT to a process {pid} other than MS-Windows} expand({expr} [, {nosuf} [, {list}]]) *expand()* Expand wildcards and the following special keywords in {expr}. diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index 63c167d79a..aa2b69ad97 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -462,10 +462,16 @@ func s:PromptCallback(text) call s:SendCommand(a:text) endfunc -" Function called when pressing CTRL-C in the prompt buffer. +" Function called when pressing CTRL-C in the prompt buffer and when placing a +" breakpoint. func s:PromptInterrupt() - "call ch_log('Interrupting gdb') - call system('kill -SIGINT ' . s:pid) + if s:pid == 0 + echoerr 'Cannot interrupt gdb, did not find a process ID' + else + "call ch_log('Interrupting gdb') + " Using job_stop(s:gdbjob, 'int') does not work. + call debugbreak(s:pid) + endif endfunc " Function called when gdb outputs text. @@ -691,7 +697,11 @@ func s:SetBreakpoint() let do_continue = 0 if !s:stopped let do_continue = 1 - call s:SendCommand('-exec-interrupt') + if s:way == 'prompt' + call s:PromptInterrupt() + else + call s:SendCommand('-exec-interrupt') + endif sleep 10m endif " Use the fname:lnum format, older gdb can't handle --source. diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 7b5845e18b..df2e6bd415 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -7315,9 +7315,7 @@ dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr) return dict; } -/* - * Find window specified by "vp" in tabpage "tp". - */ +// Find window specified by "vp" in tabpage "tp". win_T * find_win_by_nr( typval_T *vp, diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 1ca6b75b7e..17d9cc56aa 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -82,6 +82,7 @@ return { ctxset={args={1, 2}}, ctxsize={}, cursor={args={1, 3}}, + debugbreak={args={1, 1}}, deepcopy={args={1, 2}}, delete={args={1,2}}, deletebufline={args={2,3}}, diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 48e2ef8c51..36782e4223 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1408,9 +1408,31 @@ static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = 0; } -/* - * "deepcopy()" function - */ +// "debugbreak()" function +static void f_debugbreak(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + int pid; + + rettv->vval.v_number = FAIL; + pid = (int)tv_get_number(&argvars[0]); + if (pid == 0) { + EMSG(_(e_invarg)); + } else { +#ifdef WIN32 + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); + + if (hProcess != NULL) { + DebugBreakProcess(hProcess); + CloseHandle(hProcess); + rettv->vval.v_number = OK; + } +#else + uv_kill(pid, SIGINT); +#endif + } +} + +// "deepcopy()" function static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int noref = 0; diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 1f74bada41..df92b2c036 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -2971,7 +2971,10 @@ static char_u *u_save_line(linenr_T lnum) bool bufIsChanged(buf_T *buf) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { - return !bt_dontwrite(buf) && (buf->b_changed || file_ff_differs(buf, true)); + // In a "prompt" buffer we do respect 'modified', so that we can control + // closing the window by setting or resetting that option. + return (!bt_dontwrite(buf) || bt_prompt(buf)) + && (buf->b_changed || file_ff_differs(buf, true)); } // Return true if any buffer has changes. Also buffers that are not written.