nginx源码学习——错误处理

本文探讨了nginx的错误处理,从main入口函数开始,重点解析了ngx_strerror_init函数在错误码和错误信息初始化中的作用。由于strerror()和strerror_r()在信号处理函数中不可用,ngx_sys_errlist数组被用作替代方案,但其在Linux上可能导致链接器警告。ngx_strerror函数用于根据错误码获取错误信息,确保了在不同场景下的安全使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2015-05-09 wcdj


nginx在的main入口函数中(src/core/nginx.c),首先会调用ngx_strerror_init函数完成对错误码和错误信息的初始化,为什么这么做呢?继续看下内部实现。

此函数定义在src/os/unix/ngx_errno.c中:

static ngx_str_t  *ngx_sys_errlist;
static ngx_str_t   ngx_unknown_error = ngx_string("Unknown error");

ngx_uint_t
ngx_strerror_init(void)
{
    char       *msg;
    u_char     *p;
    size_t      len;
    ngx_err_t   err;

    /*
     * ngx_strerror() is not ready to work at this stage, therefore,
     * malloc() is used and possible errors are logged using strerror().
     */

    len = NGX_SYS_NERR * sizeof(ngx_str_t);

    ngx_sys_errlist = malloc(len);
    if (ngx_sys_errlist == NULL) {
        goto failed;
    }

    for (err = 0; err < NGX_SYS_NERR; err++) {
        msg = strerror(err);
        len = ngx_strlen(msg);

        p = malloc(len);
        if (p == NULL) {
            goto failed;
        }

        ngx_memcpy(p, msg, len);
        ngx_sys_errlist[err].len = len;
        ngx_sys_errlist[err].data = p;
    }

    return NGX_OK;

failed:

    err = errno;
    ngx_log_stderr(0, "malloc(%uz) failed (%d: %s)", len, err, strerror(err));

    return NGX_ERROR;
}
可以看到此函数会动态创建一个包含NGX_SYS_NERR(此大小是在自动化脚本auto/unix生成的)个ngx_str_t元素的数组ngx_sys_errlist,用于记录错误码[0,NGX_SYS_NERR-1]对应的每一个错误信息描述。为什么这么做,其实在src/os/unix/ngx_errno.c中,作者已经有注释说明:

/*
 * The strerror() messages are copied because:
 *
 * 1) strerror() and strerror_r() functions are not Async-Signal-Safe,
 *    therefore, they cannot be used in signal handlers;
 *
 * 2) a direct sys_errlist[] array may be used instead of these functions,
 *    but Linux linker warns about its usage:
 *
 * warning: `sys_errlist' is deprecated; use `strerror' or `strerror_r' instead
 * warning: `sys_nerr' is deprecated; use `strerror' or `strerror_r' instead
 *
 *    causing false bug reports.
 */

作者解释为什么要把strerror()对应的错误信息描述复制一份,即ngx_sys_errlist。原因如下:

1)strerror()和strerror_r()函数都不是Async-Signal-Safe,因此,它们不能用在信号的处理函数中;

2)但是使用ngx_sys_errlist数组代替strerror()和strerror_r()函数,Linux上的链接器会产生告警;

使用ngx_sys_errlist数组实际是调用src/os/unix/ngx_errno.c中的ngx_strerror函数:

u_char *
ngx_strerror(ngx_err_t err, u_char *errstr, size_t size)
{
    ngx_str_t  *msg;

    msg = ((ngx_uint_t) err < NGX_SYS_NERR) ? &ngx_sys_errlist[err]:
                                              &ngx_unknown_error;
    size = ngx_min(size, msg->len);

    return ngx_cpymem(errstr, msg->data, size);
}

即,ngx_strerror函数会根据错误码入参,将ngx_sys_errlist数组中的对应的错误信息拷贝给调用者提供的buffer中,供调用者使用。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值