changeset 3787:e294f37401c0

use copied strerror() messages and autoconfigured sys_nerr value
author Igor Sysoev <igor@sysoev.ru>
date Thu, 25 Nov 2010 11:04:03 +0000
parents 8a8eb335313d
children b50daa26aa22
files auto/feature auto/unix src/core/nginx.c src/core/ngx_log.c src/os/unix/ngx_errno.c src/os/unix/ngx_errno.h src/os/unix/ngx_process.c src/os/win32/ngx_errno.c src/os/win32/ngx_errno.h
diffstat 9 files changed, 106 insertions(+), 98 deletions(-) [+]
line wrap: on
line diff
--- a/auto/feature
+++ b/auto/feature
@@ -65,6 +65,24 @@ if [ -x $NGX_AUTOTEST ]; then
             fi
         ;;
 
+        value)
+            # /bin/sh is used to intercept "Killed" or "Abort trap" messages
+            if /bin/sh -c $NGX_AUTOTEST >/dev/null 2>&1; then
+                echo " found"
+                ngx_found=yes
+
+                cat << END >> $NGX_AUTO_CONFIG_H
+
+#ifndef $ngx_feature_name
+#define $ngx_feature_name  `$NGX_AUTOTEST`
+#endif
+
+END
+            else
+                echo " found but is not working"
+            fi
+        ;;
+
         bug)
             # /bin/sh is used to intercept "Killed" or "Abort trap" messages
             if /bin/sh -c $NGX_AUTOTEST >/dev/null 2>&1; then
--- a/auto/unix
+++ b/auto/unix
@@ -109,37 +109,13 @@ ngx_feature_test="char buf[1]; ssize_t n
 . auto/feature
 
 
-ngx_feature="strerror_r()"
-ngx_feature_name="NGX_HAVE_STRERROR_R"
-ngx_feature_run=yes
-ngx_feature_incs="#include <string.h>"
+ngx_feature="sys_nerr"
+ngx_feature_name="NGX_SYS_NERR"
+ngx_feature_run=value
+ngx_feature_incs='#include <stdio.h>'
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="char buf[1024]; long n; n = strerror_r(1, buf, 1024);
-                  if (n < 0 || n > 1024) return 1;"
-. auto/feature
-
-
-# GNU style strerror_r() returns not length, but pointer
-
-ngx_feature="gnu style strerror_r()"
-ngx_feature_name="NGX_HAVE_GNU_STRERROR_R"
-ngx_feature_run=yes
-ngx_feature_incs="#include <string.h>"
-ngx_feature_path=
-ngx_feature_libs=
-ngx_feature_test="char buf[1024]; long n; n = strerror_r(1, buf, 1024);
-                  if (n >= 0 && n < 1024) return 1;"
-. auto/feature
-
-
-ngx_feature="sys_errlist[]"
-ngx_feature_name="NGX_HAVE_SYS_ERRLIST"
-ngx_feature_run=yes
-ngx_feature_incs="#include <stdio.h>"
-ngx_feature_path=
-ngx_feature_libs=
-ngx_feature_test="int n = sys_nerr; const char *p = sys_errlist[1];"
+ngx_feature_test='printf("%d", sys_nerr);'
 . auto/feature
 
 
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -270,6 +270,10 @@ main(int argc, char *const *argv)
 
     ngx_pid = ngx_getpid();
 
+    if (ngx_strerror_init() != NGX_OK) {
+        return 1;
+    }
+
     log = ngx_log_init(ngx_prefix);
     if (log == NULL) {
         return 1;
--- a/src/core/ngx_log.c
+++ b/src/core/ngx_log.c
@@ -248,7 +248,7 @@ ngx_log_errno(u_char *buf, u_char *last,
     buf = ngx_slprintf(buf, last, " (%d: ", err);
 #endif
 
-    buf = ngx_strerror_r(err, buf, last - buf);
+    buf = ngx_strerror(err, buf, last - buf);
 
     if (buf < last) {
         *buf++ = ')';
--- 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
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -60,30 +60,8 @@ typedef int               ngx_err_t;
 #define ngx_set_socket_errno(err)  errno = err
 
 
-#if (NGX_HAVE_STRERROR_R || NGX_HAVE_GNU_STRERROR_R)
-
-u_char *ngx_strerror_r(int err, u_char *errstr, size_t size);
-
-#else
-
-/* Solaris and Tru64 UNIX have thread-safe strerror() */
-
-#define ngx_strerror_r(err, errstr, size)                                    \
-    ngx_cpystrn(errstr, (u_char *) strerror(err), size)
-
-#endif
-
-
-#if (NGX_HAVE_SYS_ERRLIST)
-
-#define ngx_sigsafe_strerror(err)                                            \
-    (err > 0 && err < sys_nerr) ? sys_errlist[err] : "Unknown error"
-
-#else
-
-#define ngx_sigsafe_strerror(err)  ""
-
-#endif
+u_char *ngx_strerror(ngx_err_t err, u_char *errstr, size_t size);
+ngx_uint_t ngx_strerror_init(void);
 
 
 #endif /* _NGX_ERRNO_H_INCLUDED_ */
--- a/src/os/unix/ngx_process.c
+++ b/src/os/unix/ngx_process.c
@@ -479,17 +479,15 @@ ngx_process_get_status(void)
              */
 
             if (err == NGX_ECHILD) {
-                ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
-                              "waitpid() failed (%d: %s)",
-                              err, ngx_sigsafe_strerror(err));
+                ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, err,
+                              "waitpid() failed");
                 return;
             }
 
 #endif
 
-            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
-                          "waitpid() failed (%d: %s)",
-                          err, ngx_sigsafe_strerror(err));
+            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err,
+                          "waitpid() failed");
             return;
         }
 
--- a/src/os/win32/ngx_errno.c
+++ b/src/os/win32/ngx_errno.c
@@ -9,7 +9,7 @@
 
 
 u_char *
-ngx_strerror_r(ngx_err_t err, u_char *errstr, size_t size)
+ngx_strerror(ngx_err_t err, u_char *errstr, size_t size)
 {
     u_int          len;
     static u_long  lang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
@@ -50,3 +50,10 @@ ngx_strerror_r(ngx_err_t err, u_char *er
 
     return &errstr[++len];
 }
+
+
+ngx_uint_t
+ngx_strerror_init(void)
+{
+    return NGX_OK;
+}
--- a/src/os/win32/ngx_errno.h
+++ b/src/os/win32/ngx_errno.h
@@ -54,7 +54,9 @@ typedef DWORD                      ngx_e
 #define NGX_EALREADY               WSAEALREADY
 #define NGX_EINVAL                 WSAEINVAL
 
-u_char *ngx_strerror_r(ngx_err_t err, u_char *errstr, size_t size);
+
+u_char *ngx_strerror(ngx_err_t err, u_char *errstr, size_t size);
+ngx_uint_t ngx_strerror_init(void);
 
 
 #endif /* _NGX_ERRNO_H_INCLUDED_ */