Ubuntu 下 nginx-1.24.0 源码分析 - ngx_strerror_init()函数

news/2025/2/3 13:30:02 标签: nginx, 运维

目录

ngx_strerror_init()函数声明

ngx_int_t 类型声明定义 

intptr_t 类型 

ngx_strerror_init()函数实现

NGX_HAVE_STRERRORDESC_NP


ngx_strerror_init()函数声明

在 nginx.c 的开头引入了:

#include <ngx_core.h>

在 ngx_core.h 中引入了

#include <ngx_errno.h>

在 ngx_errno.h 这个文件中声明了 ngx_strerror_init()函数:

ngx_int_t ngx_strerror_init(void);

ngx_int_t 类型声明定义 

在ngx_config.h 中:

typedef intptr_t        ngx_int_t;

ngx_int_t 本质上是 intptr_t 类型 


intptr_t 类型 

intptr_t 是一种整数类型,它保证可以容纳指针的值,帮助我们安全地在指针和整数之间进行转换

在不同的系统和编译器中,指针的大小可能不同(比如 32 位系统和 64 位系统)

intptr_t 确保在这些系统上都能正确工作。

在我当前的Ubuntu环境下也可以通过引入

#include <unistd.h>

来使用 intptr_t 类型

在 ngx_linux_config.h 中:

#include <unistd.h>

ngx_strerror_init()函数实现

ngx_errno.c 中:

#if (NGX_HAVE_STRERRORDESC_NP)

/*
 * The strerrordesc_np() function, introduced in glibc 2.32, is
 * async-signal-safe.  This makes it possible to use it directly,
 * without copying error messages.
 */


u_char *
ngx_strerror(ngx_err_t err, u_char *errstr, size_t size)
{
    size_t       len;
    const char  *msg;

    msg = strerrordesc_np(err);

    if (msg == NULL) {
        msg = (char *) ngx_unknown_error.data;
        len = ngx_unknown_error.len;

    } else {
        len = ngx_strlen(msg);
    }

    size = ngx_min(size, len);

    return ngx_cpymem(errstr, msg, size);
}


ngx_int_t
ngx_strerror_init(void)
{
    return NGX_OK;
}


#else

/*
 * 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.
 */


static ngx_str_t  *ngx_sys_errlist;
static ngx_err_t   ngx_first_error;
static ngx_err_t   ngx_last_error;


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

    if (err >= ngx_first_error && err < ngx_last_error) {
        msg = &ngx_sys_errlist[err - ngx_first_error];

    } else {
        msg = &ngx_unknown_error;
    }

    size = ngx_min(size, msg->len);

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


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

#if (NGX_SYS_NERR)
    ngx_first_error = 0;
    ngx_last_error = NGX_SYS_NERR;

#elif (EPERM > 1000 && EPERM < 0x7fffffff - 1000)

    /*
     * If number of errors is not known, and EPERM error code has large
     * but reasonable value, guess possible error codes based on the error
     * messages returned by strerror(), starting from EPERM.  Notably,
     * this covers GNU/Hurd, where errors start at 0x40000001.
     */

    for (err = EPERM; err > EPERM - 1000; err--) {
        ngx_set_errno(0);
        msg = strerror(err);

        if (errno == EINVAL
            || msg == NULL
            || strncmp(msg, "Unknown error", 13) == 0)
        {
            continue;
        }

        ngx_first_error = err;
    }

    for (err = EPERM; err < EPERM + 1000; err++) {
        ngx_set_errno(0);
        msg = strerror(err);

        if (errno == EINVAL
            || msg == NULL
            || strncmp(msg, "Unknown error", 13) == 0)
        {
            continue;
        }

        ngx_last_error = err + 1;
    }

#else

    /*
     * If number of errors is not known, guess it based on the error
     * messages returned by strerror().
     */

    ngx_first_error = 0;

    for (err = 0; err < 1000; err++) {
        ngx_set_errno(0);
        msg = strerror(err);

        if (errno == EINVAL
            || msg == NULL
            || strncmp(msg, "Unknown error", 13) == 0)
        {
            continue;
        }

        ngx_last_error = err + 1;
    }

#endif

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

    len = (ngx_last_error - ngx_first_error) * sizeof(ngx_str_t);

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

    for (err = ngx_first_error; err < ngx_last_error; err++) {
        msg = strerror(err);

        if (msg == NULL) {
            ngx_sys_errlist[err - ngx_first_error] = ngx_unknown_error;
            continue;
        }

        len = ngx_strlen(msg);

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

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

    return NGX_OK;

failed:

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

    return NGX_ERROR;
}

#endif

这里的 ngx_strerror_init 函数的定义有 2 个

具体使用的是哪一个

这要取决于

#if (NGX_HAVE_STRERRORDESC_NP)

 

NGX_HAVE_STRERRORDESC_NP

#if (NGX_HAVE_STRERRORDESC_NP) 是一个条件编译指令,

用于检查是否支持 strerrordesc_np 函数。

strerrordesc_np 是一个 GNU 扩展函数,

定义在 <string.h> 中。

它用于返回一个描述错误码的字符串,

strerror 不同的是,

strerrordesc_np 返回的描述不会根据当前的区域设置进行翻译

NGX_HAVE_STRERRORDESC_NP 用于判断当前系统是否支持 strerrordesc_np 函数。

如果支持,则在代码中会启用与该函数相关的功能,

例如直接调用 strerrordesc_np 来获取错误描述。

由于 strerrordesc_np 是 GNU 扩展,不是所有系统都支持。

Nginx 通过配置脚本检测系统是否支持该函数,

并在支持的情况下定义 NGX_HAVE_STRERRORDESC_NP

如果系统不支持 strerrordesc_np

Nginx 可能会使用其他方式(如 strerror)来获取错误描述。


ngx_errno.c 的开头引入了

#include <ngx_config.h>

ngx_config.h 中引入了

ngx_linux_config.h 这个头文件

在 ngx_linux_config.h 中引入了

#include <ngx_auto_config.h>

在 objs/ngx_auto_config.h  中:

#ifndef NGX_HAVE_STRERRORDESC_NP
#define NGX_HAVE_STRERRORDESC_NP  1
#endif

这里定义了 NGX_HAVE_STRERRORDESC_NP

 这个宏为 1


回到 ngx_errno.c 中 对于

#if (NGX_HAVE_STRERRORDESC_NP)

这个条件成立

于是使用的 ngx_strerror_init 函数的定义就是

ngx_int_t
ngx_strerror_init(void)
{
    return NGX_OK;
}

这里 NGX_OK 这个宏的定义在哪里呢?

在 ngx_errno.c 的开头引入了

#include <ngx_core.h>

打开 ngx_core.h 可以找到这样一行代码

#define  NGX_OK          0


http://www.niftyadmin.cn/n/5840846.html

相关文章

【回溯+剪枝】回溯算法的概念 全排列问题

文章目录 46. 全排列Ⅰ. 什么是回溯算法❓❓❓Ⅱ. 回溯算法的应用1、组合问题2、排列问题3、子集问题 Ⅲ. 解题思路&#xff1a;回溯 剪枝 46. 全排列 46. 全排列 ​ 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 …

HTB:Alert[WriteUP]

目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用ffuf对alert.htb域名进行子域名FUZZ 使用go…

pytorch基于GloVe实现的词嵌入

PyTorch 实现 GloVe&#xff08;Global Vectors for Word Representation&#xff09; 的完整代码&#xff0c;使用 中文语料 进行训练&#xff0c;包括 共现矩阵构建、模型定义、训练和测试。 1. GloVe 介绍 基于词的共现信息&#xff08;不像 Word2Vec 使用滑动窗口预测&…

C++ 哈希封装详解

文章目录 1.buckets1.1 load_factor和max_load_factor1.2 reserve和rehash1.3 bucket_count1.4 bucket_size 2.哈希表的底层2.1 iterator的实现2.2 operator2.3 HashTable.h2.4 Unorderedmap.h2.5 Uorderedset.h 1.buckets 1.1 load_factor和max_load_factor load_factor负载…

JavaScript系列(54)--性能优化技术详解

JavaScript性能优化技术详解 ⚡ 今天&#xff0c;让我们继续深入研究JavaScript的性能优化技术。掌握这些技术对于构建高性能的JavaScript应用至关重要。 性能优化基础概念 &#x1f3af; &#x1f4a1; 小知识&#xff1a;JavaScript性能优化涉及多个方面&#xff0c;包括代…

js对象方法大全

JavaScript中Object构造函数的方法 Object构造函数的方法节 Object.assign() 通过复制一个或多个对象来创建一个新的对象。 Object.create() 使用指定的原型对象和属性创建一个新对象。 Object.defineProperty() 给对象添加一个属性并指定该属性的配置。 Object.definePr…

【JavaScript】Web API事件流、事件委托

目录 1.事件流 1.1 事件流和两个阶段说明 1.2 事件捕获 1.3 事件冒泡 1.4 阻止冒泡 1.5 解绑事件 L0 事件解绑 L2 事件解绑 鼠标经过事件的区别 两种注册事件的区别 2.事件委托 案例 tab栏切换改造 3.其他事件 3.1 页面加载事件 3.2 页面滚动事件 3.2 页面滚…

Rust 变量特性:不可变、和常量的区别、 Shadowing

Rust 变量特性&#xff1a;不可变、和常量的区别、 Shadowing Rust 是一门以安全性和性能著称的系统编程语言&#xff0c;其变量系统设计独特且强大。本文将从三个角度介绍 Rust 变量的核心特性&#xff1a;可变性&#xff08;Mutability&#xff09;、变量与常量的区别&#…