summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2022-02-08 10:49:28 +0800
committerGitHub <[email protected]>2022-02-08 10:49:28 +0800
commit6b74a4dcd274cf96f3b224975ca8a4580ebc0f65 (patch)
treec38cbda0839b5a278e9d7431449a0d4576bb54f0
parentc80d0c5638f83d7de838a09554daa48800c71fe3 (diff)
parenta4a168088d6032427769b0c9f1405e2eebcd5c66 (diff)
Merge pull request #2032 from xmake-io/catch
catch ctrl-c to get backtrace of stuck
-rw-r--r--CHANGELOG.md2
-rw-r--r--core/src/xmake/engine.c75
-rw-r--r--xmake/core/base/coroutine.lua6
-rw-r--r--xmake/core/base/os.lua22
-rw-r--r--xmake/plugins/show/lists/envs.lua2
5 files changed, 91 insertions, 16 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c82fd5000..2cd9552bb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@
* [#2021](https://github.com/xmake-io/xmake/issues/2021): Support Swift for linux and windows
* [#2024](https://github.com/xmake-io/xmake/issues/2024): Add asn1c support
* [#2031](https://github.com/xmake-io/xmake/issues/2031): Support linker scripts and version scripts for add_files
+* [#2033](https://github.com/xmake-io/xmake/issues/2033): Catch ctrl-c to get current backtrace for debugging stuck
### Bugs fixed
@@ -1214,6 +1215,7 @@
* [#2021](https://github.com/xmake-io/xmake/issues/2021): 支持 Linux/Windows 下构建 Swift 程序
* [#2024](https://github.com/xmake-io/xmake/issues/2024): 添加 asn1c 支持
* [#2031](https://github.com/xmake-io/xmake/issues/2031): 为 add_files 增加 linker scripts 和 version scripts 支持
+* [#2033](https://github.com/xmake-io/xmake/issues/2033): 捕获 ctrl-c 去打印当前运行栈,用于调试分析卡死问题
### Bugs 修复
diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c
index e87fce465..efc89977c 100644
--- a/core/src/xmake/engine.c
+++ b/core/src/xmake/engine.c
@@ -36,12 +36,15 @@
#elif defined(TB_CONFIG_OS_MACOSX) || defined(TB_CONFIG_OS_IOS)
# include <unistd.h>
# include <mach-o/dyld.h>
+# include <signal.h>
#elif defined(TB_CONFIG_OS_LINUX) || defined(TB_CONFIG_OS_BSD) || defined(TB_CONFIG_OS_ANDROID)
# include <unistd.h>
+# include <signal.h>
#endif
#ifdef TB_CONFIG_OS_BSD
-# include <sys/types.h>
-# include <sys/sysctl.h>
+# include <sys/types.h>
+# include <sys/sysctl.h>
+# include <signal.h>
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -448,6 +451,9 @@ static luaL_Reg const g_tty_functions[] =
, { tb_null, tb_null }
};
+// the lua global instance for signal handler
+static lua_State* g_lua = tb_null;
+
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
@@ -492,16 +498,14 @@ static tb_bool_t xm_engine_save_arguments(xm_engine_t* engine, tb_int_t argc, tb
// _ARGV = table_new
lua_setglobal(engine->lua, "_ARGV");
-
- // ok
return tb_true;
}
+
static tb_size_t xm_engine_get_program_file(xm_engine_t* engine, tb_char_t* path, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(engine && path && maxn, tb_false);
- // done
tb_bool_t ok = tb_false;
do
{
@@ -563,16 +567,14 @@ static tb_size_t xm_engine_get_program_file(xm_engine_t* engine, tb_char_t* path
lua_pushstring(engine->lua, path);
lua_setglobal(engine->lua, "_PROGRAM_FILE");
}
-
- // ok?
return ok;
}
+
static tb_bool_t xm_engine_get_program_directory(xm_engine_t* engine, tb_char_t* path, tb_size_t maxn, tb_char_t const* programfile)
{
// check
tb_assert_and_check_return_val(engine && path && maxn, tb_false);
- // done
tb_bool_t ok = tb_false;
do
{
@@ -652,12 +654,12 @@ static tb_bool_t xm_engine_get_program_directory(xm_engine_t* engine, tb_char_t*
// ok?
return ok;
}
+
static tb_bool_t xm_engine_get_project_directory(xm_engine_t* engine, tb_char_t* path, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(engine && path && maxn, tb_false);
- // done
tb_bool_t ok = tb_false;
do
{
@@ -688,6 +690,41 @@ static tb_bool_t xm_engine_get_project_directory(xm_engine_t* engine, tb_char_t*
// ok?
return ok;
}
+
+#if defined(TB_CONFIG_OS_WINDOWS) || defined(SIGINT)
+static tb_void_t xm_engine_dump_traceback(lua_State* lua)
+{
+ // @note it's not safe, but it doesn't matter, we're just trying to get the stack backtrace for debugging
+ lua_getglobal(lua, "debug");
+ lua_getfield(lua, -1, "traceback");
+ lua_replace(lua, -2);
+ lua_pushvalue(lua, 1);
+ lua_call(lua, 1, 1);
+ tb_trace_i("%s", lua_tostring(lua, -1));
+}
+#endif
+
+#if defined(TB_CONFIG_OS_WINDOWS)
+static BOOL WINAPI xm_engine_signal_handler(DWORD signo)
+{
+ if (signo == CTRL_C_EVENT && g_lua)
+ {
+ xm_engine_dump_traceback(g_lua);
+ tb_abort();
+ }
+ return TRUE;
+}
+#elif defined(SIGINT)
+static tb_void_t xm_engine_signal_handler(tb_int_t signo)
+{
+ if (signo == SIGINT && g_lua)
+ {
+ xm_engine_dump_traceback(g_lua);
+ tb_abort();
+ }
+}
+#endif
+
static tb_void_t xm_engine_init_host(xm_engine_t* engine)
{
// check
@@ -733,6 +770,7 @@ static tb_void_t xm_engine_init_host(xm_engine_t* engine)
lua_pushstring(engine->lua, subhost? subhost : "unknown");
lua_setglobal(engine->lua, "_SUBHOST");
}
+
static tb_void_t xm_engine_init_arch(xm_engine_t* engine)
{
// check
@@ -803,6 +841,7 @@ static tb_void_t xm_engine_init_arch(xm_engine_t* engine)
lua_pushstring(engine->lua, subarch);
lua_setglobal(engine->lua, "_SUBARCH");
}
+
static tb_void_t xm_engine_init_features(xm_engine_t* engine)
{
// check
@@ -832,6 +871,21 @@ static tb_void_t xm_engine_init_features(xm_engine_t* engine)
lua_setglobal(engine->lua, "_FEATURES");
}
+static tb_void_t xm_engine_init_signal(xm_engine_t* engine)
+{
+ // we enable it to catch the current lua stack in ctrl-c signal handler if XMAKE_PROFILE=stuck
+ tb_char_t data[64] = {0};
+ if (!tb_environment_first("XMAKE_PROFILE", data, sizeof(data)) || tb_strcmp(data, "stuck"))
+ return ;
+
+ g_lua = engine->lua;
+#if defined(TB_CONFIG_OS_WINDOWS)
+ SetConsoleCtrlHandler(xm_engine_signal_handler, TRUE);
+#elif defined(SIGINT)
+ signal(SIGINT, xm_engine_signal_handler);
+#endif
+}
+
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
@@ -915,6 +969,9 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c
// init features
xm_engine_init_features(engine);
+ // init signal
+ xm_engine_init_signal(engine);
+
// get version
tb_version_t const* version = xm_version();
tb_assert_and_check_break(version);
diff --git a/xmake/core/base/coroutine.lua b/xmake/core/base/coroutine.lua
index 2f1c347a8..43a5d6d8a 100644
--- a/xmake/core/base/coroutine.lua
+++ b/xmake/core/base/coroutine.lua
@@ -31,8 +31,6 @@ coroutine._resume = coroutine._resume or coroutine.resume
-- resume coroutine
function coroutine.resume(co, ...)
-
- -- resume it
local ok, results = coroutine._resume(co, ...)
if not ok then
@@ -47,12 +45,8 @@ function coroutine.resume(co, ...)
errors = results:sub(pos + 1)
end
end
-
- -- failed
return false, errors
end
-
- -- ok
return true, results
end
diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua
index 18b59f61c..19f22e88f 100644
--- a/xmake/core/base/os.lua
+++ b/xmake/core/base/os.lua
@@ -268,6 +268,23 @@ function os._deduplicate_pathenv(value)
return value
end
+-- trace process for profile(stuck,trace)?
+function os._is_tracing_process()
+ local is_tracing = os._IS_TRACING_PROCESS
+ if is_tracing == nil then
+ local profile = os.getenv("XMAKE_PROFILE")
+ if profile then
+ profile = profile:trim()
+ if profile == "trace" or profile == "stuck" then
+ is_tracing = true
+ end
+ end
+ is_tracing = is_tracing or false
+ os._IS_TRACING_PROCESS = is_tracing
+ end
+ return is_tracing
+end
+
-- match files or directories
--
-- @param pattern the search pattern
@@ -749,6 +766,11 @@ function os.execv(program, argv, opt)
local proc = process.openv(filename, argv or {}, openopt)
if proc ~= nil then
+ -- trace process
+ if os._is_tracing_process() then
+ utils.cprint("%s: ${color.dump.string}%s %s${clear}", proc, filename, argv and os.args(argv) or "")
+ end
+
-- wait process
local waitok, status = proc:wait(-1)
if waitok > 0 then
diff --git a/xmake/plugins/show/lists/envs.lua b/xmake/plugins/show/lists/envs.lua
index 4092901fa..8e66db1e8 100644
--- a/xmake/plugins/show/lists/envs.lua
+++ b/xmake/plugins/show/lists/envs.lua
@@ -36,7 +36,7 @@ function main()
XMAKE_RAMDIR = {"Set the ramdisk directory.", os.getenv("XMAKE_RAMDIR")},
XMAKE_RCFILES = {"Set the runtime configuration files.", path.joinenv(project.rcfiles())},
XMAKE_TMPDIR = {"Set the temporary directory.", os.tmpdir()},
- XMAKE_PROFILE = {"Start profiler, e.g. perf, trace.", os.getenv("XMAKE_PROFILE")},
+ XMAKE_PROFILE = {"Start profiler, e.g. perf, trace, stuck.", os.getenv("XMAKE_PROFILE")},
XMAKE_PKG_CACHEDIR = {"Set the cache directory of packages.", os.getenv("XMAKE_PKG_CACHEDIR")},
XMAKE_PKG_INSTALLDIR = {"Set the install directory of packages.", os.getenv("XMAKE_PACKAGEDIR")}}
local width = 24