mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-28 20:10:08 +01:00
test: replace hand-rolled backtrace function with gstack
Let's use something that specializes in that task and does a better job of it than whatever we'll come up with. Due to how it's implemented the stacktrace will always show waitpid() as frame 0 now but we can live with that. gstack prints to stdout but litest_log() uses stderr, so we cannot just call system(), we have do do the pipe/fork/exec/waitpid/read dance. We could use that to filter the #0 frame showing waidpid() from gstack but meh. This drops the libunwind and addr2line dependency and replaces it with gstack instead. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
3a9c8aa77d
commit
c8e0e94c00
3 changed files with 43 additions and 172 deletions
|
|
@ -41,9 +41,9 @@ variables:
|
|||
# See the documentation here: #
|
||||
# https://wayland.freedesktop.org/libinput/doc/latest/building_libinput.html #
|
||||
###############################################################################
|
||||
FEDORA_RPMS: 'git gcc gcc-c++ pkgconf-pkg-config meson check-devel libudev-devel libevdev-devel doxygen graphviz python3-sphinx python3-recommonmark valgrind binutils libwacom-devel cairo-devel gtk3-devel glib2-devel mtdev-devel'
|
||||
UBUNTU_DEBS: 'git gcc g++ pkg-config meson check libudev-dev libevdev-dev doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx-rtd-theme valgrind binutils libwacom-dev libcairo2-dev libgtk-3-dev libglib2.0-dev libmtdev-dev'
|
||||
ARCH_PKGS: 'git gcc pkgconfig meson check libsystemd libevdev doxygen graphviz python-sphinx python-recommonmark valgrind binutils libwacom gtk3 mtdev '
|
||||
FEDORA_RPMS: 'git gcc gcc-c++ pkgconf-pkg-config meson check-devel libudev-devel libevdev-devel doxygen graphviz python3-sphinx python3-recommonmark valgrind libwacom-devel cairo-devel gtk3-devel glib2-devel mtdev-devel'
|
||||
UBUNTU_DEBS: 'git gcc g++ pkg-config meson check libudev-dev libevdev-dev doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx-rtd-theme valgrind libwacom-dev libcairo2-dev libgtk-3-dev libglib2.0-dev libmtdev-dev'
|
||||
ARCH_PKGS: 'git gcc pkgconfig meson check libsystemd libevdev doxygen graphviz python-sphinx python-recommonmark valgrind libwacom gtk3 mtdev '
|
||||
FREEBSD_BUILD_PKGS: 'meson'
|
||||
FREEBSD_PKGS: 'libepoll-shim libudev-devd libevdev libwacom gtk3 libmtdev '
|
||||
############################ end of package lists #############################
|
||||
|
|
|
|||
11
meson.build
11
meson.build
|
|
@ -643,18 +643,12 @@ executable('test-build-cxx',
|
|||
if get_option('tests')
|
||||
dep_check = dependency('check', version : '>= 0.9.10')
|
||||
valgrind = find_program('valgrind')
|
||||
addr2line = find_program('addr2line')
|
||||
|
||||
if addr2line.found()
|
||||
config_h.set('HAVE_ADDR2LINE', '1')
|
||||
config_h.set_quoted('ADDR2LINE', addr2line.path())
|
||||
endif
|
||||
|
||||
leftover_rules = find_program('test/check-leftover-udev-rules.sh')
|
||||
test('leftover-rules', leftover_rules, is_parallel : false)
|
||||
|
||||
dep_libunwind = dependency('libunwind', required : false)
|
||||
config_h.set10('HAVE_LIBUNWIND', dep_libunwind.found())
|
||||
gstack = find_program('gstack', required : false)
|
||||
config_h.set10('HAVE_GSTACK', gstack.found())
|
||||
|
||||
# for inhibit support during test run
|
||||
dep_libsystemd = dependency('libsystemd', version : '>= 221', required : false)
|
||||
|
|
@ -748,7 +742,6 @@ if get_option('tests')
|
|||
deps_litest = [
|
||||
dep_libinput,
|
||||
dep_check,
|
||||
dep_libunwind,
|
||||
dep_udev,
|
||||
dep_libevdev,
|
||||
dep_dl,
|
||||
|
|
|
|||
198
test/litest.c
198
test/litest.c
|
|
@ -103,175 +103,53 @@ static inline char *litest_install_quirks(struct list *created_files_list);
|
|||
#define litest_vlog(...) { /* __VA_ARGS__ */ }
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBUNWIND
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
static char cwd[PATH_MAX];
|
||||
|
||||
static bool
|
||||
litest_backtrace_get_lineno(const char *executable,
|
||||
unw_word_t addr,
|
||||
char *file_return,
|
||||
int *line_return)
|
||||
{
|
||||
#if HAVE_ADDR2LINE
|
||||
FILE* f;
|
||||
char buffer[PATH_MAX];
|
||||
char *s;
|
||||
unsigned int i;
|
||||
|
||||
if (!cwd[0]) {
|
||||
if (getcwd(cwd, sizeof(cwd)) == NULL)
|
||||
cwd[0] = 0; /* contents otherwise undefined. */
|
||||
}
|
||||
|
||||
sprintf (buffer,
|
||||
ADDR2LINE " -C -e %s -i %lx",
|
||||
executable,
|
||||
(unsigned long) addr);
|
||||
|
||||
f = popen(buffer, "r");
|
||||
if (f == NULL) {
|
||||
litest_log("Failed to execute: %s\n", buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer[0] = '?';
|
||||
if (fgets(buffer, sizeof(buffer), f) == NULL) {
|
||||
pclose(f);
|
||||
return false;
|
||||
}
|
||||
pclose(f);
|
||||
|
||||
if (buffer[0] == '?')
|
||||
return false;
|
||||
|
||||
s = strrchr(buffer, ':');
|
||||
if (!s)
|
||||
return false;
|
||||
|
||||
*s = '\0';
|
||||
s++;
|
||||
sscanf(s, "%d", line_return);
|
||||
|
||||
/* now strip cwd from buffer */
|
||||
s = buffer;
|
||||
i = 0;
|
||||
while(i < strlen(cwd) && *s != '\0' && cwd[i] == *s) {
|
||||
*s = '\0';
|
||||
s++;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
*(--s) = '.';
|
||||
strcpy(file_return, s);
|
||||
|
||||
return true;
|
||||
#else /* HAVE_ADDR2LINE */
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
litest_backtrace(void)
|
||||
{
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t context;
|
||||
unw_word_t off;
|
||||
unw_proc_info_t pip;
|
||||
int ret;
|
||||
char procname[256];
|
||||
Dl_info dlinfo;
|
||||
#if HAVE_GSTACK
|
||||
pid_t parent, child;
|
||||
int pipefd[2];
|
||||
|
||||
pip.unwind_info = NULL;
|
||||
ret = unw_getcontext(&context);
|
||||
if (ret) {
|
||||
litest_log("unw_getcontext failed: %s [%d]\n",
|
||||
unw_strerror(ret),
|
||||
ret);
|
||||
if (pipe(pipefd) == -1)
|
||||
return;
|
||||
|
||||
parent = getpid();
|
||||
child = fork();
|
||||
|
||||
if (child == 0) {
|
||||
char pid[8];
|
||||
|
||||
close(pipefd[0]);
|
||||
dup2(pipefd[1], STDOUT_FILENO);
|
||||
|
||||
sprintf(pid, "%d", parent);
|
||||
|
||||
execlp("gstack", "gstack", pid, NULL);
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
ret = unw_init_local(&cursor, &context);
|
||||
if (ret) {
|
||||
litest_log("unw_init_local failed: %s [%d]\n",
|
||||
unw_strerror(ret),
|
||||
ret);
|
||||
return;
|
||||
/* parent */
|
||||
char buf[1024];
|
||||
int status, nread;
|
||||
|
||||
close(pipefd[1]);
|
||||
waitpid(child, &status, 0);
|
||||
|
||||
status = WEXITSTATUS(status);
|
||||
if (status != 0) {
|
||||
litest_log("ERROR: gstack failed, no backtrace available: %s\n",
|
||||
strerror(status));
|
||||
} else {
|
||||
litest_log("\nBacktrace:\n");
|
||||
while ((nread = read(pipefd[0], buf, sizeof(buf) - 1)) > 0) {
|
||||
buf[nread] = '\0';
|
||||
litest_log("%s", buf);
|
||||
}
|
||||
litest_log("\n");
|
||||
}
|
||||
|
||||
litest_log("\nBacktrace:\n");
|
||||
ret = unw_step(&cursor);
|
||||
while (ret > 0) {
|
||||
char file[PATH_MAX];
|
||||
int line;
|
||||
bool have_lineno = false;
|
||||
const char *filename = "?";
|
||||
int i = 0;
|
||||
|
||||
ret = unw_get_proc_info(&cursor, &pip);
|
||||
if (ret) {
|
||||
litest_log("unw_get_proc_info failed: %s [%d]\n",
|
||||
unw_strerror(ret),
|
||||
ret);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = unw_get_proc_name(&cursor, procname, 256, &off);
|
||||
if (ret && ret != -UNW_ENOMEM) {
|
||||
if (ret != -UNW_EUNSPEC)
|
||||
litest_log("unw_get_proc_name failed: %s [%d]\n",
|
||||
unw_strerror(ret),
|
||||
ret);
|
||||
procname[0] = '?';
|
||||
procname[1] = 0;
|
||||
}
|
||||
|
||||
if (dladdr((void *)(pip.start_ip + off), &dlinfo) &&
|
||||
dlinfo.dli_fname &&
|
||||
*dlinfo.dli_fname) {
|
||||
filename = dlinfo.dli_fname;
|
||||
have_lineno = litest_backtrace_get_lineno(filename,
|
||||
(pip.start_ip + off),
|
||||
file,
|
||||
&line);
|
||||
}
|
||||
|
||||
if (have_lineno) {
|
||||
litest_log("%d: %s() (%s:%d)\n",
|
||||
i,
|
||||
procname,
|
||||
file,
|
||||
line);
|
||||
} else {
|
||||
litest_log("%d: %s (%s%s+%#x) [%p]\n",
|
||||
i,
|
||||
filename,
|
||||
procname,
|
||||
ret == -UNW_ENOMEM ? "..." : "",
|
||||
(int)off,
|
||||
(void *)(pip.start_ip + off));
|
||||
}
|
||||
|
||||
i++;
|
||||
ret = unw_step(&cursor);
|
||||
if (ret < 0)
|
||||
litest_log("unw_step failed: %s [%d]\n",
|
||||
unw_strerror(ret),
|
||||
ret);
|
||||
}
|
||||
litest_log("\n");
|
||||
}
|
||||
#else /* HAVE_LIBUNWIND */
|
||||
static inline void
|
||||
litest_backtrace(void)
|
||||
{
|
||||
/* thou shall install libunwind */
|
||||
}
|
||||
close(pipefd[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
LIBINPUT_ATTRIBUTE_PRINTF(5, 6)
|
||||
__attribute__((noreturn))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue