diff src/os/unix/ngx_errno.c @ 604:428c6e58046a NGINX_0_9_0

nginx 0.9.0 *) Feature: the "keepalive_disable" directive. *) Feature: the "map" directive supports variables as value of a defined variable. *) Feature: the "map" directive supports empty strings as value of the first parameter. *) Feature: the "map" directive supports expressions as the first parameter. *) Feature: nginx(8) manual page. Thanks to Sergey Osokin. *) Feature: Linux accept4() support. Thanks to Simon Liu. *) Workaround: elimination of Linux linker warning about "sys_errlist" and "sys_nerr"; the warning had appeared in 0.8.35. *) Bugfix: a segmentation fault might occur in a worker process, if the "auth_basic" directive was used. Thanks to Michail Laletin. *) Bugfix: compatibility with ngx_http_eval_module; the bug had appeared in 0.8.42.
author Igor Sysoev <http://sysoev.ru>
date Mon, 29 Nov 2010 00:00:00 +0300
parents 88d3e895bdf9
children eb208e0cf44d
line wrap: on
line diff
--- a/src/os/unix/ngx_errno.c
+++ b/src/os/unix/ngx_errno.c
@@ -8,54 +8,79 @@
 #include <ngx_core.h>
 
 
-#if (NGX_HAVE_STRERROR_R)
-
-u_char *
-ngx_strerror_r(int err, u_char *errstr, size_t size)
-{
-    if (size == 0) {
-        return errstr;
-    }
-
-    errstr[0] = '\0';
+/*
+ * The strerror() messages are copied because:
+ *
+ * 1) strerror() and strerror_r() functions are not Async-Signal-Safe,
+ *    therefore, they can not 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.
+ */
 
-    strerror_r(err, (char *) errstr, size);
-
-    while (*errstr && size) {
-        errstr++;
-        size--;
-    }
 
-    return errstr;
-}
+static ngx_str_t  *ngx_sys_errlist;
+static ngx_str_t   ngx_unknown_error = ngx_string("Unknown error");
 
-#elif (NGX_HAVE_GNU_STRERROR_R)
-
-/* Linux strerror_r() */
 
 u_char *
-ngx_strerror_r(int err, u_char *errstr, size_t size)
+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_uint_t
+ngx_strerror_init(void)
 {
-    char  *str;
+    char       *msg;
+    u_char     *p;
+    size_t      len;
+    ngx_err_t   err;
 
-    if (size == 0) {
-        return errstr;
+    /*
+     * ngx_strerror() is not ready to work at this stage, therefore,
+     * malloc() is used and possible errors are logged using strerror().
+     */
+
+    len = NGX_SYS_NERR * sizeof(ngx_str_t);
+
+    ngx_sys_errlist = malloc(len);
+    if (ngx_sys_errlist == NULL) {
+        goto failed;
     }
 
-    errstr[0] = '\0';
+    for (err = 0; err < NGX_SYS_NERR; err++) {
+        msg = strerror(err);
+        len = ngx_strlen(msg);
 
-    str = strerror_r(err, (char *) errstr, size);
+        p = malloc(len);
+        if (p == NULL) {
+            goto failed;
+        }
 
-    if (str != (char *) errstr) {
-        return ngx_cpystrn(errstr, (u_char *) str, size);
+        ngx_memcpy(p, msg, len);
+        ngx_sys_errlist[err].len = len;
+        ngx_sys_errlist[err].data = p;
     }
 
-    while (*errstr && size) {
-        errstr++;
-        size--;
-    }
+    return NGX_OK;
+
+failed:
 
-    return errstr;
+    err = errno;
+    ngx_log_stderr(0, "malloc(%uz) failed (%d: %s)", len, err, strerror(err));
+
+    return NGX_ERROR;
 }
-
-#endif