diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 0300b760a6..152184e75c 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -1669,6 +1669,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force bool did_save_redobuff = false; save_redo_T save_redo; const bool save_KeyTyped = KeyTyped; + ESTACK_CHECK_DECLARATION; // Quickly return if there are no autocommands for this event or // autocommands are blocked. @@ -1853,6 +1854,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force // name and lnum are filled in later estack_push(ETYPE_AUCMD, NULL, 0); + ESTACK_CHECK_SETUP; const sctx_T save_current_sctx = current_sctx; @@ -1962,6 +1964,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force filechangeshell_busy = false; autocmd_nested = save_autocmd_nested; xfree(SOURCING_NAME); + ESTACK_CHECK_NOW; estack_pop(); xfree(afile_orig); xfree(autocmd_fname); diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index e246c3b5d6..0494ff9c9c 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3788,6 +3788,7 @@ static int chk_modeline(linenr_T lnum, int flags) { char *e; int retval = OK; + ESTACK_CHECK_DECLARATION; int prev = -1; char *s = ml_get(lnum); @@ -3843,6 +3844,7 @@ static int chk_modeline(linenr_T lnum, int flags) // prepare for emsg() estack_push(ETYPE_MODELINE, "modelines", lnum); + ESTACK_CHECK_SETUP; bool end = false; while (end == false) { @@ -3899,6 +3901,7 @@ static int chk_modeline(linenr_T lnum, int flags) // careful not to go off the end } + ESTACK_CHECK_NOW; estack_pop(); xfree(linecopy); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index e9289489bb..745d697828 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1010,6 +1010,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett bool started_profiling = false; bool did_save_redo = false; save_redo_T save_redo; + ESTACK_CHECK_DECLARATION; // If depth of calling is getting too high, don't execute the function if (depth >= p_mfd) { @@ -1181,6 +1182,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett } estack_push_ufunc(fp, 1); + ESTACK_CHECK_SETUP; if (p_verbose >= 12) { no_wait_return++; verbose_enter_scroll(); @@ -1332,6 +1334,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett no_wait_return--; } + ESTACK_CHECK_NOW; estack_pop(); current_sctx = save_current_sctx; if (do_profiling_yes) { diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 7eb05a2383..d692c3e10b 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -964,6 +964,7 @@ void handle_did_throw(void) assert(current_exception != NULL); char *p = NULL; msglist_T *messages = NULL; + ESTACK_CHECK_DECLARATION; // If the uncaught exception is a user exception, report it as an // error. If it is an error exception, display the saved error @@ -985,6 +986,7 @@ void handle_did_throw(void) } estack_push(ETYPE_EXCEPT, current_exception->throw_name, current_exception->throw_lnum); + ESTACK_CHECK_SETUP; current_exception->throw_name = NULL; discard_current_exception(); // uses IObuff if 'verbose' @@ -1009,6 +1011,7 @@ void handle_did_throw(void) xfree(p); } xfree(SOURCING_NAME); + ESTACK_CHECK_NOW; estack_pop(); } diff --git a/src/nvim/main.c b/src/nvim/main.c index 65ad96f4e3..dfe30b5dbe 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1918,6 +1918,7 @@ static void exe_pre_commands(mparm_T *parmp) { char **cmds = parmp->pre_commands; int cnt = parmp->n_pre_commands; + ESTACK_CHECK_DECLARATION; if (cnt <= 0) { return; @@ -1925,10 +1926,12 @@ static void exe_pre_commands(mparm_T *parmp) curwin->w_cursor.lnum = 0; // just in case.. estack_push(ETYPE_ARGS, _("pre-vimrc command line"), 0); + ESTACK_CHECK_SETUP; current_sctx.sc_sid = SID_CMDARG; for (int i = 0; i < cnt; i++) { do_cmdline_cmd(cmds[i]); } + ESTACK_CHECK_NOW; estack_pop(); current_sctx.sc_sid = 0; TIME_MSG("--cmd commands"); @@ -1937,6 +1940,8 @@ static void exe_pre_commands(mparm_T *parmp) // Execute "+", "-c" and "-S" arguments. static void exe_commands(mparm_T *parmp) { + ESTACK_CHECK_DECLARATION; + // We start commands on line 0, make "vim +/pat file" match a // pattern on line 1. But don't move the cursor when an autocommand // with g`" was used. @@ -1945,6 +1950,7 @@ static void exe_commands(mparm_T *parmp) curwin->w_cursor.lnum = 0; } estack_push(ETYPE_ARGS, "command line", 0); + ESTACK_CHECK_SETUP; current_sctx.sc_sid = SID_CARG; current_sctx.sc_seq = 0; for (int i = 0; i < parmp->n_commands; i++) { @@ -1953,6 +1959,7 @@ static void exe_commands(mparm_T *parmp) xfree(parmp->commands[i]); } } + ESTACK_CHECK_NOW; estack_pop(); current_sctx.sc_sid = 0; if (curwin->w_cursor.lnum == 0) { @@ -2149,18 +2156,21 @@ static void source_startup_scripts(const mparm_T *const parmp) static int execute_env(char *env) FUNC_ATTR_NONNULL_ALL { + ESTACK_CHECK_DECLARATION; char *initstr = os_getenv(env); if (initstr == NULL) { return FAIL; } estack_push(ETYPE_ENV, env, 0); + ESTACK_CHECK_SETUP; const sctx_T save_current_sctx = current_sctx; current_sctx.sc_sid = SID_ENV; current_sctx.sc_seq = 0; current_sctx.sc_lnum = 0; do_cmdline_cmd(initstr); + ESTACK_CHECK_NOW; estack_pop(); current_sctx = save_current_sctx; diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 9152f132ce..9bc9ddcac3 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -2092,6 +2092,7 @@ static int do_source_ext(char *const fname, const bool check_other, const int is scriptitem_T *si = NULL; proftime_T wait_start; bool trigger_source_post = false; + ESTACK_CHECK_DECLARATION; CLEAR_FIELD(cookie); char *fname_exp = NULL; @@ -2255,6 +2256,7 @@ static int do_source_ext(char *const fname, const bool check_other, const int is // Keep the sourcing name/lnum, for recursive calls. estack_push(ETYPE_SCRIPT, si != NULL ? si->sn_name : fname_exp, 0); + ESTACK_CHECK_SETUP; if (l_do_profiling == PROF_YES && si != NULL) { bool forceit = false; @@ -2316,6 +2318,7 @@ static int do_source_ext(char *const fname, const bool check_other, const int is if (got_int) { emsg(_(e_interr)); } + ESTACK_CHECK_NOW; estack_pop(); if (p_verbose > 1) { verbose_enter(); diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h index 43cdbd20dd..8a1d2dadd9 100644 --- a/src/nvim/runtime.h +++ b/src/nvim/runtime.h @@ -45,4 +45,19 @@ enum { DIP_DIRFILE = 0x200, ///< find both files and directories }; +#ifdef ABORT_ON_INTERNAL_ERROR +# define ESTACK_CHECK_DECLARATION int estack_len_before +# define ESTACK_CHECK_SETUP do { estack_len_before = exestack.ga_len; } while (0) +# define ESTACK_CHECK_NOW \ + do { \ + if (estack_len_before != exestack.ga_len) { \ + siemsg("Exestack length expected: %d, actual: %d", estack_len_before, exestack.ga_len); \ + } \ + } while (0) +#else +# define ESTACK_CHECK_DECLARATION do {} while (0) +# define ESTACK_CHECK_SETUP do {} while (0) +# define ESTACK_CHECK_NOW do {} while (0) +#endif + #include "runtime.h.generated.h" diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index bd63b3b3e2..87cf6e55c4 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -608,6 +608,7 @@ slang_T *spell_load_file(char *fname, char *lang, slang_T *old_lp, bool silent) slang_T *lp = NULL; int res; bool did_estack_push = false; + ESTACK_CHECK_DECLARATION; FILE *fd = os_fopen(fname, "r"); if (fd == NULL) { @@ -640,6 +641,7 @@ slang_T *spell_load_file(char *fname, char *lang, slang_T *old_lp, bool silent) // Set sourcing_name, so that error messages mention the file name. estack_push(ETYPE_SPELL, fname, 0); + ESTACK_CHECK_SETUP; did_estack_push = true; //
: @@ -838,6 +840,7 @@ endOK: fclose(fd); } if (did_estack_push) { + ESTACK_CHECK_NOW; estack_pop(); }