xref: /unit/src/nxt_errno.c (revision 703)
10Sigor@sysoev.ru 
20Sigor@sysoev.ru /*
30Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
40Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
50Sigor@sysoev.ru  */
60Sigor@sysoev.ru 
70Sigor@sysoev.ru #include <nxt_main.h>
80Sigor@sysoev.ru 
90Sigor@sysoev.ru 
100Sigor@sysoev.ru /*
110Sigor@sysoev.ru  * The strerror() messages are copied because:
120Sigor@sysoev.ru  *
130Sigor@sysoev.ru  * 1) strerror() and strerror_r() functions are not Async-Signal-Safe,
140Sigor@sysoev.ru  *    therefore, they can not be used in signal handlers;
150Sigor@sysoev.ru  *
160Sigor@sysoev.ru  * 2) a direct sys_errlist[] array may be used instead of these functions,
170Sigor@sysoev.ru  *    but Linux linker warns about this usage:
180Sigor@sysoev.ru  *
190Sigor@sysoev.ru  * warning: `sys_errlist' is deprecated; use `strerror' or `strerror_r' instead
200Sigor@sysoev.ru  * warning: `sys_nerr' is deprecated; use `strerror' or `strerror_r' instead
210Sigor@sysoev.ru  *
220Sigor@sysoev.ru  *    causing false bug reports.
230Sigor@sysoev.ru  */
240Sigor@sysoev.ru 
250Sigor@sysoev.ru static u_char *nxt_bootstrap_strerror(nxt_err_t err, u_char *errstr,
260Sigor@sysoev.ru     size_t size);
270Sigor@sysoev.ru static u_char *nxt_runtime_strerror(nxt_err_t err, u_char *errstr, size_t size);
280Sigor@sysoev.ru 
290Sigor@sysoev.ru 
300Sigor@sysoev.ru nxt_strerror_t     nxt_strerror = nxt_bootstrap_strerror;
310Sigor@sysoev.ru static nxt_str_t   *nxt_sys_errlist;
320Sigor@sysoev.ru static nxt_uint_t  nxt_sys_nerr;
330Sigor@sysoev.ru 
340Sigor@sysoev.ru 
350Sigor@sysoev.ru nxt_int_t
360Sigor@sysoev.ru nxt_strerror_start(void)
370Sigor@sysoev.ru {
380Sigor@sysoev.ru     char        *msg;
390Sigor@sysoev.ru     u_char      *p;
4010Sigor@sysoev.ru     size_t      size, length, n;
410Sigor@sysoev.ru     nxt_uint_t  err, invalid;
420Sigor@sysoev.ru 
430Sigor@sysoev.ru     /* The last entry. */
44*703Svbart@nginx.com     size = nxt_length("Unknown error");
450Sigor@sysoev.ru 
460Sigor@sysoev.ru     /*
470Sigor@sysoev.ru      * Linux has holes for error codes 41 and 58, so the loop
480Sigor@sysoev.ru      * stops only after 100 invalid codes in succession.
490Sigor@sysoev.ru      */
500Sigor@sysoev.ru 
510Sigor@sysoev.ru     for (invalid = 0; invalid < 100 && nxt_sys_nerr < 65536; nxt_sys_nerr++) {
520Sigor@sysoev.ru 
530Sigor@sysoev.ru         nxt_set_errno(0);
540Sigor@sysoev.ru         msg = strerror((int) nxt_sys_nerr);
550Sigor@sysoev.ru 
560Sigor@sysoev.ru         /*
570Sigor@sysoev.ru          * strerror() behaviour on passing invalid error code depends
580Sigor@sysoev.ru          * on OS and version:
590Sigor@sysoev.ru          *   Linux returns "Unknown error NN";
600Sigor@sysoev.ru          *   FreeBSD, NetBSD and OpenBSD return "Unknown error: NN"
610Sigor@sysoev.ru          *     and set errno to EINVAL;
620Sigor@sysoev.ru          *   Solaris 10 returns "Unknown error" and sets errno to EINVAL;
630Sigor@sysoev.ru          *   Solaris 9 returns "Unknown error";
640Sigor@sysoev.ru          *   Solaris 2 returns NULL;
650Sigor@sysoev.ru          *   MacOSX returns "Unknown error: NN";
660Sigor@sysoev.ru          *   AIX returns "Error NNN occurred.";
670Sigor@sysoev.ru          *   HP-UX returns "Unknown error" for invalid codes lesser than 250
680Sigor@sysoev.ru          *     or empty string for larger codes.
690Sigor@sysoev.ru          */
700Sigor@sysoev.ru 
710Sigor@sysoev.ru         if (msg == NULL) {
720Sigor@sysoev.ru             invalid++;
730Sigor@sysoev.ru             continue;
740Sigor@sysoev.ru         }
750Sigor@sysoev.ru 
7610Sigor@sysoev.ru         length = nxt_strlen(msg);
7710Sigor@sysoev.ru         size += length;
780Sigor@sysoev.ru 
7910Sigor@sysoev.ru         if (length == 0  /* HP-UX empty strings. */
800Sigor@sysoev.ru             || nxt_errno == NXT_EINVAL
810Sigor@sysoev.ru             || nxt_memcmp(msg, "Unknown error", 13) == 0)
820Sigor@sysoev.ru         {
830Sigor@sysoev.ru             invalid++;
840Sigor@sysoev.ru             continue;
850Sigor@sysoev.ru         }
860Sigor@sysoev.ru 
870Sigor@sysoev.ru #if (NXT_AIX)
880Sigor@sysoev.ru 
890Sigor@sysoev.ru         if (nxt_memcmp(msg, "Error ", 6) == 0
9010Sigor@sysoev.ru             && nxt_memcmp(msg + length - 10, " occurred.", 9) == 0)
910Sigor@sysoev.ru         {
920Sigor@sysoev.ru             invalid++;
930Sigor@sysoev.ru             continue;
940Sigor@sysoev.ru         }
950Sigor@sysoev.ru 
960Sigor@sysoev.ru #endif
970Sigor@sysoev.ru     }
980Sigor@sysoev.ru 
990Sigor@sysoev.ru     nxt_sys_nerr -= invalid;
1000Sigor@sysoev.ru 
1010Sigor@sysoev.ru     nxt_main_log_debug("sys_nerr: %d", nxt_sys_nerr);
1020Sigor@sysoev.ru 
1030Sigor@sysoev.ru     n = (nxt_sys_nerr + 1) * sizeof(nxt_str_t);
1040Sigor@sysoev.ru 
1050Sigor@sysoev.ru     nxt_sys_errlist = nxt_malloc(n + size);
1060Sigor@sysoev.ru     if (nxt_sys_errlist == NULL) {
1070Sigor@sysoev.ru         return NXT_ERROR;
1080Sigor@sysoev.ru     }
1090Sigor@sysoev.ru 
11098Svbart@nginx.com     p = nxt_pointer_to(nxt_sys_errlist, n);
1110Sigor@sysoev.ru 
1120Sigor@sysoev.ru     for (err = 0; err < nxt_sys_nerr; err++) {
1130Sigor@sysoev.ru         msg = strerror((int) err);
11410Sigor@sysoev.ru         length = nxt_strlen(msg);
1150Sigor@sysoev.ru 
11610Sigor@sysoev.ru         nxt_sys_errlist[err].length = length;
11710Sigor@sysoev.ru         nxt_sys_errlist[err].start = p;
1180Sigor@sysoev.ru 
11910Sigor@sysoev.ru         p = nxt_cpymem(p, msg, length);
1200Sigor@sysoev.ru     }
1210Sigor@sysoev.ru 
12210Sigor@sysoev.ru     nxt_sys_errlist[err].length = 13;
12310Sigor@sysoev.ru     nxt_sys_errlist[err].start = p;
1240Sigor@sysoev.ru     nxt_memcpy(p, "Unknown error", 13);
1250Sigor@sysoev.ru 
1260Sigor@sysoev.ru     nxt_strerror = nxt_runtime_strerror;
1270Sigor@sysoev.ru 
1280Sigor@sysoev.ru     return NXT_OK;
1290Sigor@sysoev.ru }
1300Sigor@sysoev.ru 
1310Sigor@sysoev.ru 
1320Sigor@sysoev.ru static u_char *
1330Sigor@sysoev.ru nxt_bootstrap_strerror(nxt_err_t err, u_char *errstr, size_t size)
1340Sigor@sysoev.ru {
1350Sigor@sysoev.ru     return nxt_cpystrn(errstr, (u_char *) strerror(err), size);
1360Sigor@sysoev.ru }
1370Sigor@sysoev.ru 
1380Sigor@sysoev.ru 
1390Sigor@sysoev.ru static u_char *
1400Sigor@sysoev.ru nxt_runtime_strerror(nxt_err_t err, u_char *errstr, size_t size)
1410Sigor@sysoev.ru {
1420Sigor@sysoev.ru     nxt_str_t   *msg;
1430Sigor@sysoev.ru     nxt_uint_t  n;
1440Sigor@sysoev.ru 
1450Sigor@sysoev.ru     n = nxt_min((nxt_uint_t) err, nxt_sys_nerr);
1460Sigor@sysoev.ru 
1470Sigor@sysoev.ru     msg = &nxt_sys_errlist[n];
1480Sigor@sysoev.ru 
14910Sigor@sysoev.ru     size = nxt_min(size, msg->length);
1500Sigor@sysoev.ru 
15110Sigor@sysoev.ru     return nxt_cpymem(errstr, msg->start, size);
1520Sigor@sysoev.ru }
153