stack trace на мыло!
Jul. 24th, 2005 05:36 amзнаете как неприятно возиться с gdb если бага возникает фиг знает почему, нерегулярно, и совершенно не показывает себя при наблюдении под отладчиком. вот avva, например, знает, он писал давно про отладку epoll'ов в ЖЖ. У меня, конечно, не лимон юзеров, но свои десять тысяч запросов в минуту имею. Компиляция в режиме "для gdb" тормозит всё до невозможности, а без неё как отловить косяк багов пролетающий раз в два-три дня? Ну вот, в общем, приспичило, самообучился.
Идея проста до идиотизма - имеем сигнал, segmentation fault. Хотим stacktrace.
Оказывается, фиг вам, а не стандарт. Есть что-то проприетарное, встроенное в солярку, есть свои костылики для ХП-УХ, есть какие-то намудренные средства встроенные в gcc, но чтоб я понял как это юзать, хотя вот, например, библиотека.
В общем плюнул я на совместимость, стал искать решение чисто для Линуха и нашел, практически сразу. Простенько и чистенько, backtrace().
соответственно, рождается код.
void bt()
{
int c, i;
void *addresses[10];
char **strings;
c = backtrace(addresses, 10) ;
strings = backtrace_symbols(addresses,c);
err_report(errfd, "backtrace returned: %d\n", c);
for(i = 0; i < c; i++) {
err_report(errfd, "[bt] %d: %X %s\n", i, (int)addresses[i], strings[i]);
}
}
...
/* Install signal handlers */
Signal(SIGTERM, child_sighandler); /* terminate */
Signal(SIGHUP, child_sighandler); /* restart */
Signal(SIGUSR1, child_sighandler); /* dump info */
Signal(SIGSEGV, child_sighandler); /* segfault */
static void child_sighandler(int signo)
{
switch (signo) {
...
case SIGSEGV:
bt();
abort();
}
}
вот, собственно и всё, ловушка на слонопотама поставлена, сидим ждем. а он всё не идет, гад ушастый.
p.s. а на мыло я его посылать не буду, нефиг.
Идея проста до идиотизма - имеем сигнал, segmentation fault. Хотим stacktrace.
Оказывается, фиг вам, а не стандарт. Есть что-то проприетарное, встроенное в солярку, есть свои костылики для ХП-УХ, есть какие-то намудренные средства встроенные в gcc, но чтоб я понял как это юзать, хотя вот, например, библиотека.
В общем плюнул я на совместимость, стал искать решение чисто для Линуха и нашел, практически сразу. Простенько и чистенько, backtrace().
соответственно, рождается код.
void bt()
{
int c, i;
void *addresses[10];
char **strings;
c = backtrace(addresses, 10) ;
strings = backtrace_symbols(addresses,c);
err_report(errfd, "backtrace returned: %d\n", c);
for(i = 0; i < c; i++) {
err_report(errfd, "[bt] %d: %X %s\n", i, (int)addresses[i], strings[i]);
}
}
...
/* Install signal handlers */
Signal(SIGTERM, child_sighandler); /* terminate */
Signal(SIGHUP, child_sighandler); /* restart */
Signal(SIGUSR1, child_sighandler); /* dump info */
Signal(SIGSEGV, child_sighandler); /* segfault */
static void child_sighandler(int signo)
{
switch (signo) {
...
case SIGSEGV:
bt();
abort();
}
}
вот, собственно и всё, ловушка на слонопотама поставлена, сидим ждем. а он всё не идет, гад ушастый.
p.s. а на мыло я его посылать не буду, нефиг.