首页 > 代码库 > Nginx源码完全注释(8)ngx_errno.c
Nginx源码完全注释(8)ngx_errno.c
errno.h
中的strerror(int errno)
可以确定指定的errno
的错误的提示信息。在 Nginx 中,将所有错误提示信息预先存储在一个数组里,而预先确定这个数组的大小,是在自动化脚本中完成的,如下是auto/unix
脚本:(其中自动化脚本auto/feature
的作用参考《解剖 Nginx·自动脚本篇(4)工具型脚本系列》一文)
// auto/unixngx_feature="sys_nerr"ngx_feature_name="NGX_SYS_NERR"ngx_feature_run=valuengx_feature_incs=‘#include #include ‘ngx_feature_path=ngx_feature_libs=ngx_feature_test=‘printf("%d", sys_nerr);‘. auto/feature
但是对于某些平台是没有sys_nerr
的,此时引用auto/feature
后得到的ngx_found
变量的值为no
,否则为yes
。当为no
时,则执行下面这段:
// auto/unixif [ $ngx_found = no ]; then ngx_feature="_sys_nerr" ngx_feature_name="NGX_SYS_NERR" ngx_feature_run=value ngx_feature_incs=‘#include #include ‘ ngx_feature_path= ngx_feature_libs= ngx_feature_test=‘printf("%d", _sys_nerr);‘ . auto/featurefi
上面这段会在 Cygwin 环境下起作用,因为 Cygwin 定义了_sys_nerr
。如果此后ngx_found
还是no
,则运行:
if [ $ngx_found = no ]; then ngx_feature=‘maximum errno‘ ngx_feature_name=NGX_SYS_NERR ngx_feature_run=value ngx_feature_incs=‘#include #include #include ‘ ngx_feature_path= ngx_feature_libs= ngx_feature_test=‘int n; char *p; for (n = 1; n < 1000; n++) { errno = 0; p = strerror(n); if (errno == EINVAL || p == NULL || strncmp(p, "Unknown error", 13) == 0) { break; } } printf("%d", n);‘ . auto/featurefi
上面这段会在 Solaris 上生效,因为 Solaris 没有sys_nerr
和_sys_nerr
。
这样就会在objs/ngx_auto_config.h
文件中加入如下一句;
// Mac OS X 10.8#ifndef NGX_SYS_NERR#define NGX_SYS_NERR 107#endif
// Linux ubuntu 3.2.0-30-generic-pae#ifndef NGX_SYS_NERR#define NGX_SYS_NERR 135#endif
Igor 把所有 strerror 消息都拷贝到一个数组里,他是这样解释原因的:
- 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.
如下是src/os/unix/ngx_errno.c
:
static ngx_str_t *ngx_sys_errlist;static ngx_str_t ngx_unknown_error = ngx_string("Unknown error");// 替代 strerror,传入 err 错误码、已分配内存的 errstr 指针以及其内存大小// 调用该函数后,errstr 和返回值均为给定错误码相应的错误消息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_int_tngx_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(). */ // 所有 strerror 消息的数量所需要的 ngx_str_t 的内存字节数 //(注意不是消息本身,因为小内容是存在 ngx_str_t 的 data 里的) len = NGX_SYS_NERR * sizeof(ngx_str_t); // 分配内存,注意此时是直接使用 malloc 的 // TODO 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); // 分配 len 大小的内存 p = malloc(len); if (p == NULL) { goto failed; } ngx_memcpy(p, msg, len); ngx_sys_errlist[err].len = len; ngx_sys_errlist[err].data = http://www.mamicode.com/p;"keyword" style="font-weight: bold;">return NGX_OK;failed: err = errno; ngx_log_stderr(0, "malloc(%uz) failed (%d: %s)", len, err, strerror(err)); return NGX_ERROR;}
Nginx源码完全注释(8)ngx_errno.c
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。