mirror of
https://github.com/neovim/neovim.git
synced 2025-10-05 09:26:30 +00:00
fix(logging): skip recursion, fix crash #18764
Problem: 1. The main log routine does not protect itself against recursion. log_lock() doesn't guard against recursion, it would deadlock... 2.22b52dd462
(#11501) regressed6f27f5ef91
(#10172), because set_init_1..process_spawn tries to log (see backtrace below), but the mutex isn't initialized yet. Even if the mutex were valid, we don't want early logging to fallback to stderr because that can break embedders when stdio is used for RPC. frame 1: 0x00000001001d54f4 nvim`open_log_file at log.c:205:7 frame 2: 0x00000001001d5390 nvim`logmsg(log_level=1, context="UI: ", func_name=0x0000000000000000, line_num=-1, eol=true, fmt="win_viewport") at log.c:150:20 frame : 0x000000010039aea2 nvim`ui_call_win_viewport(grid=2, win=1000, topline=0, botline=1, curline=0, curcol=0, line_count=1) at ui_events_call.generated.h:321:3 frame 4: 0x00000001003dfefc nvim`ui_ext_win_viewport(wp=0x0000000101816400) at window.c:939:5 frame 5: 0x00000001003ec5b4 nvim`win_ui_flush at window.c:7303:7 frame 6: 0x00000001003a04c0 nvim`ui_flush at ui.c:508:3 frame 7: 0x00000001002966ba nvim`do_os_system(argv=0x0000600000c0c000, input=0x0000000000000000, len=0, output=0x0000000000000000, nread=0x00007ff7bfefe830, silent=false, forward_output=false) at shell.c:894:3 frame 8: 0x0000000100295f68 nvim`os_call_shell(cmd="unset nonomatch; vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >/var/folders/gk/3tttv_md06987tlwpyp62jrw0000gn/T/nvimwwvwfD/0 ~foo", opts=kShellOptExpand | kShellOptSilent | kShellOptHideMess, extra_args=0x0000000000000000) at shell.c:663:18 frame 9: 0x0000000100295845 nvim`call_shell(cmd="unset nonomatch; vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >/var/folders/gk/3tttv_md06987tlwpyp62jrw0000gn/T/nvimwwvwfD/0 ~foo", opts=kShellOptExpand | kShellOptSilent | kShellOptHideMess, extra_shell_arg=0x0000000000000000) at shell.c:712:14 frame 10: 0x0000000100294c6f nvim`os_expand_wildcards(num_pat=1, pat=0x00007ff7bfefeb20, num_file=0x00007ff7bfefee58, file=0x00007ff7bfefee60, flags=43) at shell.c:328:7 ... frame 23: 0x000000010028ccef nvim`expand_env_esc(srcp=",~foo", dst="~foo", dstlen=4094, esc=false, one=false, prefix=0x0000000000000000) at env.c:673:17 frame 24: 0x000000010026fdd5 nvim`option_expand(opt_idx=29, val=",~foo") at option.c:1950:3 frame 25: 0x000000010026f129 nvim`set_init_1(clean_arg=false) at option.c:558:19 frame 26: 0x00000001001ea25e nvim`early_init(paramp=0x00007ff7bfeff5f0) at main.c:198:3 frame 27: 0x00000001001ea6bf nvim`main(argc=1, argv=0x00007ff7bfeff848) at main.c:255:3 Solution: 1. Check for recursion, show "internal error" message. - FUTURE: when "remote TUI" is merged, can we remove log_lock()? 2. Skip logging if log_init wasn't called yet.
This commit is contained in:
@@ -16,11 +16,11 @@
|
||||
# define NVIM_PROBE(name, n, ...)
|
||||
#endif
|
||||
|
||||
#define TRACE_LOG_LEVEL 0
|
||||
#define DEBUG_LOG_LEVEL 1
|
||||
#define INFO_LOG_LEVEL 2
|
||||
#define WARN_LOG_LEVEL 3
|
||||
#define ERROR_LOG_LEVEL 4
|
||||
#define LOGLVL_TRC 0
|
||||
#define LOGLVL_DBG 1
|
||||
#define LOGLVL_INF 2
|
||||
#define LOGLVL_WRN 3
|
||||
#define LOGLVL_ERR 4
|
||||
|
||||
#define DLOG(...)
|
||||
#define DLOGN(...)
|
||||
@@ -32,46 +32,37 @@
|
||||
#define ELOGN(...)
|
||||
|
||||
#ifndef MIN_LOG_LEVEL
|
||||
# define MIN_LOG_LEVEL INFO_LOG_LEVEL
|
||||
# define MIN_LOG_LEVEL LOGLVL_INF
|
||||
#endif
|
||||
|
||||
#define LOG(level, ...) logmsg((level), NULL, __func__, __LINE__, true, \
|
||||
__VA_ARGS__)
|
||||
#define LOG(level, ...) logmsg((level), NULL, __func__, __LINE__, true, __VA_ARGS__)
|
||||
|
||||
#if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL
|
||||
#if MIN_LOG_LEVEL <= LOGLVL_DBG
|
||||
# undef DLOG
|
||||
# undef DLOGN
|
||||
# define DLOG(...) logmsg(DEBUG_LOG_LEVEL, NULL, __func__, __LINE__, true, \
|
||||
__VA_ARGS__)
|
||||
# define DLOGN(...) logmsg(DEBUG_LOG_LEVEL, NULL, __func__, __LINE__, false, \
|
||||
__VA_ARGS__)
|
||||
# define DLOG(...) logmsg(LOGLVL_DBG, NULL, __func__, __LINE__, true, __VA_ARGS__)
|
||||
# define DLOGN(...) logmsg(LOGLVL_DBG, NULL, __func__, __LINE__, false, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if MIN_LOG_LEVEL <= INFO_LOG_LEVEL
|
||||
#if MIN_LOG_LEVEL <= LOGLVL_INF
|
||||
# undef ILOG
|
||||
# undef ILOGN
|
||||
# define ILOG(...) logmsg(INFO_LOG_LEVEL, NULL, __func__, __LINE__, true, \
|
||||
__VA_ARGS__)
|
||||
# define ILOGN(...) logmsg(INFO_LOG_LEVEL, NULL, __func__, __LINE__, false, \
|
||||
__VA_ARGS__)
|
||||
# define ILOG(...) logmsg(LOGLVL_INF, NULL, __func__, __LINE__, true, __VA_ARGS__)
|
||||
# define ILOGN(...) logmsg(LOGLVL_INF, NULL, __func__, __LINE__, false, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if MIN_LOG_LEVEL <= WARN_LOG_LEVEL
|
||||
#if MIN_LOG_LEVEL <= LOGLVL_WRN
|
||||
# undef WLOG
|
||||
# undef WLOGN
|
||||
# define WLOG(...) logmsg(WARN_LOG_LEVEL, NULL, __func__, __LINE__, true, \
|
||||
__VA_ARGS__)
|
||||
# define WLOGN(...) logmsg(WARN_LOG_LEVEL, NULL, __func__, __LINE__, false, \
|
||||
__VA_ARGS__)
|
||||
# define WLOG(...) logmsg(LOGLVL_WRN, NULL, __func__, __LINE__, true, __VA_ARGS__)
|
||||
# define WLOGN(...) logmsg(LOGLVL_WRN, NULL, __func__, __LINE__, false, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if MIN_LOG_LEVEL <= ERROR_LOG_LEVEL
|
||||
#if MIN_LOG_LEVEL <= LOGLVL_ERR
|
||||
# undef ELOG
|
||||
# undef ELOGN
|
||||
# define ELOG(...) logmsg(ERROR_LOG_LEVEL, NULL, __func__, __LINE__, true, \
|
||||
__VA_ARGS__)
|
||||
# define ELOGN(...) logmsg(ERROR_LOG_LEVEL, NULL, __func__, __LINE__, false, \
|
||||
__VA_ARGS__)
|
||||
# define ELOG(...) logmsg(LOGLVL_ERR, NULL, __func__, __LINE__, true, __VA_ARGS__)
|
||||
# define ELOGN(...) logmsg(LOGLVL_ERR, NULL, __func__, __LINE__, false, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EXECINFO_BACKTRACE
|
||||
|
Reference in New Issue
Block a user