nginx模块开发:ngx_xqw_backtrace_module

模块介绍

当nginx运行过程中收到异常退出信号SIGINT,会将当前函数调用堆栈输出到日志文件当中。除了处理SIGINT之外,还可以在模块中添加相应信号。

模块开发流程

  1. 创建配置结构体
typedef struct ngx_xqw_backtrace_conf_s{
    ngx_log_t *log; // 日志
    ngx_int_t size; // 栈最大深度
}ngx_xqw_backtrace_conf_t;

每个模块都有相应的配置结构体。
2. 实现create_conf为配置结构体分配内存,并返回相应的指针

// 初始化配置结构体
static void *
ngx_http_xqw_backtrace_create_conf(ngx_cycle_t *cycle)
{
    ngx_xqw_backtrace_conf_t *bcf = NULL;
    bcf = ngx_palloc(cycle->pool, sizeof(ngx_xqw_backtrace_conf_t));

    if (bcf == NULL)
        return NULL;

    bcf->size = NGX_CONF_UNSET;
    return bcf;
}

以上是创建结构体流程。
3. 为每个配置项设置set回调函数。如果配置项参数是数字,可以将set设置为ngx_conf_set_num_slot,否则需要自己实现。

// a、用ngx_get_conf得到该模块的结构体
// b、获取配置项中的参数 cf->cycle->elts
// c、由参数构造模块结构体中的成员
static char*
ngx_xqw_backtrace_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_str_t file, *value;
    ngx_log_t *log;
    ngx_xqw_backtrace_conf_t *bcf;

    bcf = (ngx_xqw_backtrace_conf_t *) ngx_get_conf(cf->cycle->conf_ctx, 
        ngx_xqw_backtrace_module);

    value = cf->args->elts;

    file = value[1];

    // 解析配置文件出错返回 NGX_CONF_ERROR
    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;
    bcf->log->log_level = NGX_LOG_ERR; // 每个LOGFILE都有相应的级别,
    // 需要设置好级别后才能输出到自定义的LOGFILE

    return NGX_CONF_OK;
}

以上是 解析配置项的流程
4. 初始化信号的处理函数

static ngx_int_t
ngx_init_error_signal(ngx_log_t *log)
{
    ngx_backtrace_signal_t *sigs;
    struct sigaction sa;

    // 不需要用index的循环方法
    for (sigs = ngx_backtrace_signals; sigs->name != NULL; sigs ++)
    {
        ngx_memzero(&sa, sizeof(struct sigaction));
        sa.sa_handler = sigs->handler;
        sigemptyset(&sa.sa_mask);
        if (sigaction(sigs->value, &sa, NULL) == -1)
        {
            perror("sigaction");
            return NGX_ERROR;
        }
    }

    return NGX_OK;
}

围绕sigaction实现
5. 编写异常处理函数

static void
ngx_backtrace_signal_handler(int sig)
{
    ngx_backtrace_signal_t *sigs;
    ngx_xqw_backtrace_conf_t *bcf;
    void *buff;
    size_t size;

    bcf = (ngx_xqw_backtrace_conf_t*) ngx_get_conf(ngx_cycle->conf_ctx, 
        ngx_xqw_backtrace_module);

    ngx_log_error(NGX_LOG_ERR, bcf->log, 0, "hello error\n");

    if (bcf == NULL)
        fprintf(stderr, "ngx_get_conf error\n");

    for (sigs = ngx_backtrace_signals; sigs->name != NULL; ++ sigs)
        if (sigs->value == sig)
            break;

    // 要退出了,故将信号设置为默认处理方式
    struct sigaction sa;
    ngx_memzero(&sa, sizeof(struct sigaction));
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = SIG_DFL;
    if (sigaction(sigs->value, &sa, NULL) == -1)
        perror("signal handler sigaction:");

    if (bcf->size == NGX_CONF_UNSET)
        bcf->size = MAX_STACK_SIZE;

    buff = (void *)ngx_palloc(ngx_cycle->pool, 
        bcf->size * sizeof (void *));

    if (buff == NULL)
        fprintf(stderr, "ngx_palloc error\n");

    size = backtrace(buff, bcf->size);
    backtrace_symbols_fd(buff, size, bcf->log->file->fd);

    kill(ngx_getpid(), sig);    
}

需要将信号的处理函数恢复为默认处理情况,处理完成后并再次发送该信号。

参考资料

淘宝发布的ngx_backtrace_module模块

ngx_xqw_backtrace_module下载链接

http://download.csdn.net/detail/wxq714586001/8719535

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值