src/os/unix/ngx_errno.c - nginx source code

Global variables defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>


  7. static ngx_str_t   ngx_unknown_error = ngx_string("Unknown error");


  8. #if (NGX_HAVE_STRERRORDESC_NP)

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


  14. u_char *
  15. ngx_strerror(ngx_err_t err, u_char *errstr, size_t size)
  16. {
  17.     size_t       len;
  18.     const char  *msg;

  19.     msg = strerrordesc_np(err);

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

  23.     } else {
  24.         len = ngx_strlen(msg);
  25.     }

  26.     size = ngx_min(size, len);

  27.     return ngx_cpymem(errstr, msg, size);
  28. }


  29. ngx_int_t
  30. ngx_strerror_init(void)
  31. {
  32.     return NGX_OK;
  33. }


  34. #else

  35. /*
  36. * The strerror() messages are copied because:
  37. *
  38. * 1) strerror() and strerror_r() functions are not Async-Signal-Safe,
  39. *    therefore, they cannot be used in signal handlers;
  40. *
  41. * 2) a direct sys_errlist[] array may be used instead of these functions,
  42. *    but Linux linker warns about its usage:
  43. *
  44. * warning: `sys_errlist' is deprecated; use `strerror' or `strerror_r' instead
  45. * warning: `sys_nerr' is deprecated; use `strerror' or `strerror_r' instead
  46. *
  47. *    causing false bug reports.
  48. */


  49. static ngx_str_t  *ngx_sys_errlist;
  50. static ngx_err_t   ngx_first_error;
  51. static ngx_err_t   ngx_last_error;


  52. u_char *
  53. ngx_strerror(ngx_err_t err, u_char *errstr, size_t size)
  54. {
  55.     ngx_str_t  *msg;

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

  58.     } else {
  59.         msg = &ngx_unknown_error;
  60.     }

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

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


  64. ngx_int_t
  65. ngx_strerror_init(void)
  66. {
  67.     char       *msg;
  68.     u_char     *p;
  69.     size_t      len;
  70.     ngx_err_t   err;

  71. #if (NGX_SYS_NERR)
  72.     ngx_first_error = 0;
  73.     ngx_last_error = NGX_SYS_NERR;

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

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

  81.     for (err = EPERM; err > EPERM - 1000; err--) {
  82.         ngx_set_errno(0);
  83.         msg = strerror(err);

  84.         if (errno == EINVAL
  85.             || msg == NULL
  86.             || strncmp(msg, "Unknown error", 13) == 0)
  87.         {
  88.             continue;
  89.         }

  90.         ngx_first_error = err;
  91.     }

  92.     for (err = EPERM; err < EPERM + 1000; err++) {
  93.         ngx_set_errno(0);
  94.         msg = strerror(err);

  95.         if (errno == EINVAL
  96.             || msg == NULL
  97.             || strncmp(msg, "Unknown error", 13) == 0)
  98.         {
  99.             continue;
  100.         }

  101.         ngx_last_error = err + 1;
  102.     }

  103. #else

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

  108.     ngx_first_error = 0;

  109.     for (err = 0; err < 1000; err++) {
  110.         ngx_set_errno(0);
  111.         msg = strerror(err);

  112.         if (errno == EINVAL
  113.             || msg == NULL
  114.             || strncmp(msg, "Unknown error", 13) == 0)
  115.         {
  116.             continue;
  117.         }

  118.         ngx_last_error = err + 1;
  119.     }

  120. #endif

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

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

  126.     ngx_sys_errlist = malloc(len);
  127.     if (ngx_sys_errlist == NULL) {
  128.         goto failed;
  129.     }

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

  132.         if (msg == NULL) {
  133.             ngx_sys_errlist[err - ngx_first_error] = ngx_unknown_error;
  134.             continue;
  135.         }

  136.         len = ngx_strlen(msg);

  137.         p = malloc(len);
  138.         if (p == NULL) {
  139.             goto failed;
  140.         }

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

  145.     return NGX_OK;

  146. failed:

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

  149.     return NGX_ERROR;
  150. }

  151. #endif