Replace sigsegv.c with siginfo.c and build it only when explicitly enabled

siginfo is disabled by default so building on new CPU
architectures does not require adjusting of siginfo.c anymore.

When needed, --siginfo can be used as option to ./waf configure
to enable the functionality
This commit is contained in:
Nedko Arnaudov 2023-11-07 02:44:43 +02:00
parent 36bdfb2c65
commit 994086cfd9
8 changed files with 25 additions and 233 deletions

3
.gitmodules vendored
View File

@ -4,3 +4,6 @@
[submodule "dbus/jack_control"]
path = dbus/jack_control
url = ../jack_control
[submodule "siginfo"]
path = siginfo
url = ../siginfo

View File

@ -42,7 +42,9 @@
#include "jack/jack.h"
#include "jack/jslist.h"
#include "jack/control.h"
#include "sigsegv.h"
#if SIGINFO_ENABLED
#include "../siginfo/siginfo.h"
#endif
static char * g_log_filename;
static ino_t g_log_file_ino;
@ -896,8 +898,10 @@ main (int argc, char **argv)
jack_set_error_function(jack_dbus_error_callback);
jack_set_info_function(jack_dbus_info_callback);
/* setup our SIGSEGV magic that prints nice stack in our logfile */
setup_sigsegv();
#if SIGINFO_ENABLED
/* setup our SIGSEGV magic that prints nice stack in our logfile */
setup_siginfo();
#endif
jack_info("------------------");
jack_info("jackdbus version %s built from %s on %s", JACK_VERSION, GIT_VERSION, timestamp_str);

5
dbus/siginfo.c Normal file
View File

@ -0,0 +1,5 @@
/* -*- Mode: C ; c-basic-offset: 2 -*- */
#include <jack/control.h>
#define siginfo_log jack_error
#include "../siginfo/siginfo.c"

View File

@ -1,220 +0,0 @@
/**
* This source file is used to print out a stack-trace when your program
* segfaults. It is relatively reliable and spot-on accurate.
*
* This code is in the public domain. Use it as you see fit, some credit
* would be appreciated, but is not a prerequisite for usage. Feedback
* on it's use would encourage further development and maintenance.
*
* Author: Jaco Kroon <jaco@kroon.co.za>
*
* Copyright (C) 2005 - 2008 Jaco Kroon
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
//#define NO_CPP_DEMANGLE
#define SIGSEGV_NO_AUTO_INIT
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <dlfcn.h>
#ifdef HAVE_EXECINFO_H
# include <execinfo.h>
#endif
#include <errno.h>
#ifndef NO_CPP_DEMANGLE
char * __cxa_demangle(const char * __mangled_name, char * __output_buffer, size_t * __length, int * __status);
#endif
#include "jack/control.h"
#if defined(REG_RIP)
# define SIGSEGV_STACK_IA64
# define REGFORMAT "%016lx"
#elif defined(REG_EIP)
# define SIGSEGV_STACK_X86
# define REGFORMAT "%08x"
#else
# define SIGSEGV_STACK_GENERIC
# define REGFORMAT "%x"
#endif
#ifdef __APPLE__
// TODO : does not compile yet on OSX
static void signal_segv(int signum, siginfo_t* info, void*ptr)
{}
#else
#include <ucontext.h>
static void signal_segv(int signum, siginfo_t* info, void*ptr) {
static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"};
const char *si_code_str;
ucontext_t *ucontext = (ucontext_t*)ptr;
#if (defined(HAVE_UCONTEXT) && defined(HAVE_NGREG)) || defined(HAVE_EXECINFO_H)
size_t i;
#endif
#if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
int f = 0;
Dl_info dlinfo;
void **bp = 0;
void *ip = 0;
#else
void *bt[20];
char **strings;
size_t sz;
#endif
if (signum == SIGSEGV)
{
jack_error("Segmentation Fault!");
}
else if (signum == SIGABRT)
{
jack_error("Abort!");
}
else if (signum == SIGILL)
{
jack_error("Illegal instruction!");
}
else if (signum == SIGFPE)
{
jack_error("Floating point exception!");
}
else
{
jack_error("Unknown bad signal caught!");
}
if (info->si_code >= 0 && info->si_code < 3)
si_code_str = si_codes[info->si_code];
else
si_code_str = "unknown";
jack_error("info.si_signo = %d", signum);
jack_error("info.si_errno = %d", info->si_errno);
jack_error("info.si_code = %d (%s)", info->si_code, si_code_str);
jack_error("info.si_addr = %p", info->si_addr);
#if defined(HAVE_UCONTEXT) && defined(HAVE_NGREG)
for(i = 0; i < NGREG; i++)
jack_error("reg[%02d] = 0x" REGFORMAT, i,
#if defined(HAVE_UCONTEXT_GP_REGS)
ucontext->uc_mcontext.gp_regs[i]
#elif defined(HAVE_UCONTEXT_UC_REGS)
ucontext->uc_mcontext.uc_regs[i]
#elif defined(HAVE_UCONTEXT_MC_GREGS)
ucontext->uc_mcontext.mc_gregs[i]
#elif defined(HAVE_UCONTEXT_GREGS)
ucontext->uc_mcontext.gregs[i]
#endif
);
#endif /* defined(HAVE_UCONTEXT) && defined(HAVE_NGREG) */
#if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
# if defined(SIGSEGV_STACK_IA64)
ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP];
bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP];
# elif defined(SIGSEGV_STACK_X86)
ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP];
bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP];
# endif
jack_error("Stack trace:");
while(bp && ip) {
if(!dladdr(ip, &dlinfo))
break;
const char *symname = dlinfo.dli_sname;
#ifndef NO_CPP_DEMANGLE
int status;
char *tmp = __cxa_demangle(symname, NULL, 0, &status);
if(status == 0 && tmp)
symname = tmp;
#endif
jack_error("% 2d: %p <%s+%u> (%s)",
++f,
ip,
symname,
(unsigned)(ip - dlinfo.dli_saddr),
dlinfo.dli_fname);
#ifndef NO_CPP_DEMANGLE
if(tmp)
free(tmp);
#endif
if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main"))
break;
ip = bp[1];
bp = (void**)bp[0];
}
#else
# ifdef HAVE_EXECINFO_H
jack_error("Stack trace (non-dedicated):");
sz = backtrace(bt, 20);
strings = backtrace_symbols(bt, sz);
for(i = 0; i < sz; ++i)
jack_error("%s", strings[i]);
# else
jack_error("Stack trace not available");
# endif
#endif
jack_error("End of stack trace");
exit (-1);
}
#endif
int setup_sigsegv() {
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_sigaction = signal_segv;
#ifdef SA_SIGINFO
action.sa_flags = SA_SIGINFO;
#endif
if(sigaction(SIGSEGV, &action, NULL) < 0) {
jack_error("sigaction failed. errno is %d (%s)", errno, strerror(errno));
return 0;
}
if(sigaction(SIGILL, &action, NULL) < 0) {
jack_error("sigaction failed. errno is %d (%s)", errno, strerror(errno));
return 0;
}
if(sigaction(SIGABRT, &action, NULL) < 0) {
jack_error("sigaction failed. errno is %d (%s)", errno, strerror(errno));
return 0;
}
if(sigaction(SIGFPE, &action, NULL) < 0) {
jack_error("sigaction failed. errno is %d (%s)", errno, strerror(errno));
return 0;
}
return 1;
}
#ifndef SIGSEGV_NO_AUTO_INIT
static void __attribute((constructor)) init(void) {
setup_sigsegv();
}
#endif

View File

@ -1,9 +0,0 @@
#ifndef __SIGSEGV_H__
#define __SIGSEGV_H__
#ifdef __cplusplus
extern "C"
#endif
int setup_sigsegv();
#endif

View File

@ -81,7 +81,6 @@ def build(bld):
'xml.c',
'xml_expat.c',
'xml_write_raw.c',
'sigsegv.c',
'reserve.c',
]
obj.use = ['JACKSERVER']
@ -100,6 +99,10 @@ def build(bld):
'../macosx/uptime.c',
]
obj.use += ['PTHREAD', 'DL', 'DBUS-1', 'EXPAT']
if bld.env['BUILD_SIGINFO']:
obj.source += [
'siginfo.c',
]
obj.target = 'jackdbus'
# process org.jackaudio.service.in -> org.jackaudio.service

1
siginfo Submodule

@ -0,0 +1 @@
Subproject commit ba0ec23f8d74c749584910e7c30baebcd368f98a

View File

@ -67,6 +67,7 @@ def options(opt):
help='Target platform for cross-compiling, e.g. cygwin or win32',
)
opt.add_option('--debug', action='store_true', default=False, dest='debug', help='Build debuggable binaries')
opt.add_option('--siginfo', action='store_true', default=False, dest='siginfo', help="Log backtrace on fatal signal")
#opt.set_auto_options_define('HAVE_%s')
#opt.set_auto_options_style('yesno_and_hack')
@ -269,7 +270,10 @@ def configure(conf):
flags.add_candcxx('-g')
flags.add_link('-g')
conf.env['BUILD_SIGINFO'] = Options.options.siginfo
conf.define('JACK_VERSION', conf.env['JACK_VERSION'])
conf.define('SIGINFO_ENABLED', conf.env['BUILD_SIGINFO'])
conf.write_config_header('config.h', remove=False)
conf.recurse('dbus')
@ -290,6 +294,7 @@ def configure(conf):
conf.msg('Install prefix', conf.env['PREFIX'], color='CYAN')
conf.msg('Library directory', conf.all_envs['']['LIBDIR'], color='CYAN')
display_feature(conf, 'Build debuggable binaries', conf.env['BUILD_DEBUG'])
display_feature(conf, 'Build with siginfo', conf.env['BUILD_SIGINFO'])
tool_flags = [
('C compiler flags', ['CFLAGS', 'CPPFLAGS']),