将所有的错误码errno以及错误描述strerror(errno)提前存储到ngx_sys_errlist中,用于解决异步信号安全的问题。
/*
* Copyright (C) Igor Sysoev
* Copyright (C) Nginx, Inc.
*/
#include <ngx_config.h>
#include <ngx_core.h>
/*
* The strerror() messages are copied because:
* strerror()的错误描述由于以下原因才被拷贝到ngx_sys_errlist中
*
* 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(造成错误的bug报告).
*/
static ngx_str_t *ngx_sys_errlist;
static ngx_str_t ngx_unknown_error = ngx_string("Unknown error");
/*
* 解析者 : wenpeng_lu
* 时间 :2017/4/8
* 功能 : 根据错误的状态码返回错误的描述信息
* 参数 : err : 错误的状态码
* errstr : 用于写入错误描述信息的缓冲区
* size : errstr缓冲区的长度
* 返回值 : 返回下次在errstr追加数据的起始地址
* 注意 : size代表errstr缓存区的长度,要足够容纳错误描述的长度
* 若size过小,错误描述信息会被截取
*/
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);
// #define ngx_cpymem(dst, src, n) (((u_char *) memcpy(dst, src, n)) + (n))
return ngx_cpymem(errstr, msg->data, size);
}
/*
* 解析者 : wenpeng_lu
* 时间 :2017/4/8
* 功能 : 初始化ngx_sys_errlist
* 返回值 : NGX_OK(0) 成功
* NGX_ERROR(-1) 失败
* 问题 : 初始化ngx_sys_errlist时申请的内存何时释放
* 用途 : 为了解决异步信号安全问题,故用于信号处理中
* 减少了strerror()的调用,更快
*/
ngx_int_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().
*
* 此时ngx_strerror()还不可用,此处malloc()出错,还需要调用strerror()
*/
len = NGX_SYS_NERR * sizeof(ngx_str_t);
// ngx_sys_errlist申请的内存何时释放
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;
}