Coverage Report

Created: 2026-01-03 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/unit/src/nxt_errno.c
Line
Count
Source
1
2
/*
3
 * Copyright (C) Igor Sysoev
4
 * Copyright (C) NGINX, Inc.
5
 */
6
7
#include <nxt_main.h>
8
9
10
/*
11
 * The strerror() messages are copied because:
12
 *
13
 * 1) strerror() and strerror_r() functions are not Async-Signal-Safe,
14
 *    therefore, they can not be used in signal handlers;
15
 *
16
 * 2) a direct sys_errlist[] array may be used instead of these functions,
17
 *    but Linux linker warns about this usage:
18
 *
19
 * warning: `sys_errlist' is deprecated; use `strerror' or `strerror_r' instead
20
 * warning: `sys_nerr' is deprecated; use `strerror' or `strerror_r' instead
21
 *
22
 *    causing false bug reports.
23
 */
24
25
static u_char *nxt_bootstrap_strerror(nxt_err_t err, u_char *errstr,
26
    size_t size);
27
static u_char *nxt_runtime_strerror(nxt_err_t err, u_char *errstr, size_t size);
28
29
30
nxt_strerror_t     nxt_strerror = nxt_bootstrap_strerror;
31
static nxt_str_t   *nxt_sys_errlist;
32
static nxt_uint_t  nxt_sys_nerr;
33
34
35
nxt_int_t
36
nxt_strerror_start(void)
37
2
{
38
2
    char        *msg;
39
2
    u_char      *p;
40
2
    size_t      size, length, n;
41
2
    nxt_uint_t  err, invalid;
42
43
    /* The last entry. */
44
2
    size = nxt_length("Unknown error");
45
46
    /*
47
     * Linux has holes for error codes 41 and 58, so the loop
48
     * stops only after 100 invalid codes in succession.
49
     */
50
51
466
    for (invalid = 0; invalid < 100 && nxt_sys_nerr < 65536; nxt_sys_nerr++) {
52
53
464
        nxt_set_errno(0);
54
464
        msg = strerror((int) nxt_sys_nerr);
55
56
        /*
57
         * strerror() behaviour on passing invalid error code depends
58
         * on OS and version:
59
         *   Linux returns "Unknown error NN";
60
         *   FreeBSD, NetBSD and OpenBSD return "Unknown error: NN"
61
         *     and set errno to EINVAL;
62
         *   Solaris 10 returns "Unknown error" and sets errno to EINVAL;
63
         *   Solaris 9 returns "Unknown error";
64
         *   Solaris 2 returns NULL;
65
         *   MacOSX returns "Unknown error: NN";
66
         *   AIX returns "Error NNN occurred.";
67
         *   HP-UX returns "Unknown error" for invalid codes lesser than 250
68
         *     or empty string for larger codes.
69
         */
70
71
464
        if (msg == NULL) {
72
0
            invalid++;
73
0
            continue;
74
0
        }
75
76
464
        length = nxt_strlen(msg);
77
464
        size += length;
78
79
464
        if (length == 0  /* HP-UX empty strings. */
80
464
            || nxt_errno == NXT_EINVAL
81
464
            || memcmp(msg, "Unknown error", 13) == 0)
82
200
        {
83
200
            invalid++;
84
200
            continue;
85
200
        }
86
87
#if (NXT_AIX)
88
89
        if (memcmp(msg, "Error ", 6) == 0
90
            && memcmp(msg + length - 10, " occurred.", 9) == 0)
91
        {
92
            invalid++;
93
            continue;
94
        }
95
96
#endif
97
464
    }
98
99
2
    nxt_sys_nerr -= invalid;
100
101
2
    nxt_main_log_debug("sys_nerr: %d", nxt_sys_nerr);
102
103
2
    n = (nxt_sys_nerr + 1) * sizeof(nxt_str_t);
104
105
2
    nxt_sys_errlist = nxt_malloc(n + size);
106
2
    if (nxt_sys_errlist == NULL) {
107
0
        return NXT_ERROR;
108
0
    }
109
110
2
    p = nxt_pointer_to(nxt_sys_errlist, n);
111
112
266
    for (err = 0; err < nxt_sys_nerr; err++) {
113
264
        msg = strerror((int) err);
114
264
        length = nxt_strlen(msg);
115
116
264
        nxt_sys_errlist[err].length = length;
117
264
        nxt_sys_errlist[err].start = p;
118
119
264
        p = nxt_cpymem(p, msg, length);
120
264
    }
121
122
2
    nxt_sys_errlist[err].length = 13;
123
2
    nxt_sys_errlist[err].start = p;
124
2
    nxt_memcpy(p, "Unknown error", 13);
125
126
2
    nxt_strerror = nxt_runtime_strerror;
127
128
2
    return NXT_OK;
129
2
}
130
131
132
static u_char *
133
nxt_bootstrap_strerror(nxt_err_t err, u_char *errstr, size_t size)
134
0
{
135
0
    return nxt_cpystrn(errstr, (u_char *) strerror(err), size);
136
0
}
137
138
139
static u_char *
140
nxt_runtime_strerror(nxt_err_t err, u_char *errstr, size_t size)
141
0
{
142
0
    nxt_str_t   *msg;
143
0
    nxt_uint_t  n;
144
145
0
    n = nxt_min((nxt_uint_t) err, nxt_sys_nerr);
146
147
0
    msg = &nxt_sys_errlist[n];
148
149
0
    size = nxt_min(size, msg->length);
150
151
0
    return nxt_cpymem(errstr, msg->start, size);
152
0
}