Skip to content

Commit e3eadc5

Browse files
committed
sysprof: fix sampling outside the VM
If the signal by timer is handled outside the VM, the `g->vmstate` equals zero. This was interpreted by the sysprof as the trace with the corresponding number and leads to the assertion failure. This patch fixes that by checking this case and dumping only the host stack outside the VM. Resolves tarantool/tarantool#11185 Resolves tarantool/tarantool#11429 Reviewed-by: Sergey Bronnikov <[email protected]> Signed-off-by: Sergey Kaplun <[email protected]> (cherry picked from commit 9794698)
1 parent b9e0615 commit e3eadc5

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

src/lj_sysprof.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,15 @@ static void sysprof_record_sample(struct sysprof *sp, siginfo_t *info)
297297
{
298298
global_State *g = sp->g;
299299
uint32_t _vmstate = ~(uint32_t)(g->vmstate);
300-
uint32_t vmstate = _vmstate < LJ_VMST_TRACE ? _vmstate : LJ_VMST_TRACE;
300+
uint32_t vmstate;
301+
302+
/* `g->vmstate` is 0 outside the VM. Hence, dump only the host stack. */
303+
if (g->vmstate == 0)
304+
vmstate = LJ_VMST_INTERP;
305+
else if (_vmstate < LJ_VMST_TRACE)
306+
vmstate = _vmstate;
307+
else
308+
vmstate = LJ_VMST_TRACE;
301309

302310
lj_assertX(pthread_self() == sp->thread,
303311
"bad thread during sysprof record sample");
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include "lua.h"
2+
#include "lauxlib.h"
3+
4+
/* Need for skipcond for OS and ARCH. */
5+
#include "lj_arch.h"
6+
7+
#include "test.h"
8+
9+
#if LJ_HASSYSPROF && !defined(LUAJIT_USE_VALGRIND)
10+
#include "utils.h"
11+
#endif /* LJ_HASSYSPROF && !defined(LUAJIT_USE_VALGRIND) */
12+
13+
#include <signal.h>
14+
#include <unistd.h>
15+
16+
/*
17+
* Check that there is no assertion failure during the dump of the
18+
* sample outside the VM.
19+
*/
20+
static int stream_trace_assert(void *test_state)
21+
{
22+
lua_State *L = test_state;
23+
(void)luaL_dostring(L,
24+
"misc.sysprof.start({mode = 'C', path = '/dev/null'})");
25+
26+
pid_t self_pid = getpid();
27+
/* Dump the single sample outside the VM. */
28+
kill(self_pid, SIGPROF);
29+
30+
/* No assertion fail -- stop the profiler and exit. */
31+
(void)luaL_dostring(L, "misc.sysprof.stop()");
32+
return TEST_EXIT_SUCCESS;
33+
}
34+
35+
int main(void)
36+
{
37+
#if LUAJIT_USE_VALGRIND
38+
UNUSED(stream_trace_assert);
39+
return skip_all("Disabled due to #10803");
40+
#elif !LJ_HASSYSPROF
41+
UNUSED(stream_trace_assert);
42+
return skip_all("Sysprof is disabled");
43+
#else /* LUAJIT_DISABLE_SYSPROF */
44+
if (LUAJIT_OS != LUAJIT_OS_LINUX)
45+
return skip_all("Sysprof is implemented for Linux only");
46+
if (LUAJIT_TARGET != LUAJIT_ARCH_X86
47+
&& LUAJIT_TARGET != LUAJIT_ARCH_X64)
48+
return skip_all("Sysprof is implemented for x86_64 only");
49+
50+
lua_State *L = utils_lua_init();
51+
52+
const struct test_unit tgroup[] = {
53+
test_unit_def(stream_trace_assert)
54+
};
55+
const int test_result = test_run_group(tgroup, L);
56+
utils_lua_close(L);
57+
return test_result;
58+
#endif /* LUAJIT_DISABLE_SYSPROF */
59+
}

0 commit comments

Comments
 (0)