# HG changeset patch # User Igor Sysoev # Date 1290683043 0 # Node ID e294f37401c0def77adc92629c7e6d2ddf9ff0f0 # Parent 8a8eb335313d4d3910954d792ef212ab72f231f8 use copied strerror() messages and autoconfigured sys_nerr value diff --git a/auto/feature b/auto/feature --- 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 diff --git a/auto/unix b/auto/unix --- 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 " +ngx_feature="sys_nerr" +ngx_feature_name="NGX_SYS_NERR" +ngx_feature_run=value +ngx_feature_incs='#include ' 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 " -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 " -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 diff --git a/src/core/nginx.c b/src/core/nginx.c --- 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; diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c --- 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++ = ')'; diff --git a/src/os/unix/ngx_errno.c b/src/os/unix/ngx_errno.c --- a/src/os/unix/ngx_errno.c +++ b/src/os/unix/ngx_errno.c @@ -8,54 +8,79 @@ #include -#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 diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h --- 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_ */ diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c --- 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; } diff --git a/src/os/win32/ngx_errno.c b/src/os/win32/ngx_errno.c --- 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; +} diff --git a/src/os/win32/ngx_errno.h b/src/os/win32/ngx_errno.h --- 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_ */