Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: master
Fetching contributors…

Cannot retrieve contributors at this time

229 lines (167 sloc) 5.491 kB
/*
* Copyright (C) 2010-2012 Alibaba Group Holding Limited
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <execinfo.h>
#define NGX_BACKTRACE_DEFAULT_STACK_MAX_SIZE 30
static char *ngx_backtrace_files(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static void ngx_error_signal_handler(int signo);
static ngx_int_t ngx_backtrace_init_worker(ngx_cycle_t *cycle);
static void *ngx_backtrace_create_conf(ngx_cycle_t *cycle);
typedef struct {
int signo;
char *signame;
char *name;
void (*handler)(int signo);
} ngx_signal_t;
typedef struct {
ngx_log_t *log;
ngx_int_t max_stack_size;
} ngx_backtrace_conf_t;
static ngx_signal_t ngx_backtrace_signals[] = {
{ SIGABRT, "SIGABRT", "", ngx_error_signal_handler },
#ifdef SIGBUS
{ SIGBUS, "SIGBUS", "", ngx_error_signal_handler },
#endif
{ SIGFPE, "SIGFPE", "", ngx_error_signal_handler },
{ SIGILL, "SIGILL", "", ngx_error_signal_handler },
{ SIGIOT, "SIGIOT", "", ngx_error_signal_handler },
{ SIGSEGV, "SIGSEGV", "", ngx_error_signal_handler },
{ 0, NULL, "", NULL }
};
static ngx_command_t ngx_backtrace_commands[] = {
{ ngx_string("backtrace_log"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_backtrace_files,
0,
0,
NULL },
{ ngx_string("backtrace_max_stack_size"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
0,
offsetof(ngx_backtrace_conf_t, max_stack_size),
NULL },
ngx_null_command
};
static ngx_core_module_t ngx_backtrace_module_ctx = {
ngx_string("backtrace"),
ngx_backtrace_create_conf,
NULL
};
ngx_module_t ngx_backtrace_module = {
NGX_MODULE_V1,
&ngx_backtrace_module_ctx, /* module context */
ngx_backtrace_commands, /* module directives */
NGX_CORE_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
ngx_backtrace_init_worker, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static ngx_int_t
ngx_init_error_signals(ngx_log_t *log)
{
ngx_signal_t *sig;
struct sigaction sa;
for (sig = ngx_backtrace_signals; sig->signo != 0; sig++) {
ngx_memzero(&sa, sizeof(struct sigaction));
sa.sa_handler = sig->handler;
sigemptyset(&sa.sa_mask);
if (sigaction(sig->signo, &sa, NULL) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
"sigaction(%s) failed", sig->signame);
return NGX_ERROR;
}
}
return NGX_OK;
}
static void
ngx_error_signal_handler(int signo)
{
void *buffer;
size_t size;
ngx_log_t *log;
ngx_signal_t *sig;
struct sigaction sa;
ngx_backtrace_conf_t *bcf;
for (sig = ngx_backtrace_signals; sig->signo != 0; sig++) {
if (sig->signo == signo) {
break;
}
}
bcf = (ngx_backtrace_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
ngx_backtrace_module);
log = bcf->log ? bcf->log : ngx_cycle->log;
ngx_log_error(NGX_LOG_ERR, log, 0,
"nginx coredump by signal %d (%s)", signo, sig->signame);
ngx_memzero(&sa, sizeof(struct sigaction));
sa.sa_handler = SIG_DFL;
sigemptyset(&sa.sa_mask);
if (sigaction(signo, &sa, NULL) == -1) {
ngx_log_error(NGX_LOG_ERR, log, ngx_errno,
"sigaction(%s) failed", sig->signame);
}
if (bcf->max_stack_size == NGX_CONF_UNSET) {
bcf->max_stack_size = NGX_BACKTRACE_DEFAULT_STACK_MAX_SIZE;
}
buffer = ngx_pcalloc(ngx_cycle->pool, sizeof(void *) * bcf->max_stack_size);
if (buffer == NULL) {
goto invalid;
}
size = backtrace(buffer, bcf->max_stack_size);
backtrace_symbols_fd(buffer, size, log->file->fd);
invalid:
kill(ngx_getpid(), signo);
}
static char *
ngx_backtrace_files(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
ngx_str_t file, *value;
ngx_log_t *log;
ngx_backtrace_conf_t *bcf;
bcf = (ngx_backtrace_conf_t *) ngx_get_conf(cf->cycle->conf_ctx,
ngx_backtrace_module);
value = cf->args->elts;
file = value[1];
if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
return NGX_CONF_ERROR;
}
log = ngx_log_create(cf->cycle, &file);
if (log == NULL) {
return NGX_CONF_ERROR;
}
bcf->log = log;
return NGX_CONF_OK;
}
static ngx_int_t
ngx_backtrace_init_worker(ngx_cycle_t *cycle)
{
if (ngx_init_error_signals(cycle->log) == NGX_ERROR) {
return NGX_ERROR;
}
return NGX_OK;
}
static void *
ngx_backtrace_create_conf(ngx_cycle_t *cycle)
{
ngx_backtrace_conf_t *bcf;
bcf = ngx_pcalloc(cycle->pool, sizeof(ngx_backtrace_conf_t));
if (bcf == NULL) {
return NULL;
}
/*
* set by ngx_pcalloc()
*
* bcf->log = NULL;
*/
bcf->max_stack_size = NGX_CONF_UNSET;
return bcf;
}
Jump to Line
Something went wrong with that request. Please try again.