Welcome! Log In Create A New Profile

Advanced

[njs] Improved error messages for module loading failures.

Anonymous User
October 21, 2024 09:08PM
details: https://github.com/nginx/njs/commit/ed36e94242de38e88a6cc536404609fc72bf6456
branches: master
commit: ed36e94242de38e88a6cc536404609fc72bf6456
user: Dmitry Volyntsev <xeioex@nginx.com>
date: Fri, 18 Oct 2024 18:24:49 -0700
description:
Improved error messages for module loading failures.

There are several reasons why a file cannot be opened. Without
extra information, especially in containerized environments, these
problems are difficult to debug. Adding errno status to the
error output helps identify the root cause.

Additionally, error messages are now aligned between njs and QuickJS.

---
nginx/ngx_js.c | 350 ++++++++++++++++++++++++++++++++++++++++++++++-
nginx/ngx_js.h | 1 +
src/njs.h | 2 +
src/njs_module.c | 2 +-
src/njs_parser.c | 9 +-
src/test/njs_unit_test.c | 4 +-
test/shell_test_njs.exp | 4 +-
7 files changed, 362 insertions(+), 10 deletions(-)

diff --git a/nginx/ngx_js.c b/nginx/ngx_js.c
index 152045f0..f70288cf 100644
--- a/nginx/ngx_js.c
+++ b/nginx/ngx_js.c
@@ -1979,10 +1979,15 @@ ngx_qjs_module_loader(JSContext *cx, const char *module_name, void *opaque)
info.name.start = (u_char *) module_name;
info.name.length = njs_strlen(module_name);

+ errno = 0;
ret = ngx_js_module_lookup(conf, &info);
if (ret != NJS_OK) {
- JS_ThrowReferenceError(cx, "could not load module filename '%s'",
- module_name);
+ if (errno != 0) {
+ JS_ThrowReferenceError(cx, "Cannot load module \"%s\" "
+ "(%s:%s)", module_name,
+ ngx_js_errno_string(errno), strerror(errno));
+ }
+
return NULL;
}

@@ -3764,8 +3769,14 @@ ngx_js_module_loader(njs_vm_t *vm, njs_external_ptr_t external, njs_str_t *name)

info.name = *name;

+ errno = 0;
ret = ngx_js_module_lookup(conf, &info);
if (njs_slow_path(ret != NJS_OK)) {
+ if (errno != 0) {
+ njs_vm_ref_error(vm, "Cannot load module \"%V\" (%s:%s)", name,
+ ngx_js_errno_string(errno), strerror(errno));
+ }
+
return NULL;
}

@@ -4076,6 +4087,341 @@ ngx_js_monotonic_time(void)
}


+#define ngx_js_errno_case(e) \
+ case e: \
+ return #e;
+
+
+const char*
+ngx_js_errno_string(int errnum)
+{
+ switch (errnum) {
+#ifdef EACCES
+ ngx_js_errno_case(EACCES);
+#endif
+
+#ifdef EADDRINUSE
+ ngx_js_errno_case(EADDRINUSE);
+#endif
+
+#ifdef EADDRNOTAVAIL
+ ngx_js_errno_case(EADDRNOTAVAIL);
+#endif
+
+#ifdef EAFNOSUPPORT
+ ngx_js_errno_case(EAFNOSUPPORT);
+#endif
+
+#ifdef EAGAIN
+ ngx_js_errno_case(EAGAIN);
+#endif
+
+#ifdef EWOULDBLOCK
+#if EAGAIN != EWOULDBLOCK
+ ngx_js_errno_case(EWOULDBLOCK);
+#endif
+#endif
+
+#ifdef EALREADY
+ ngx_js_errno_case(EALREADY);
+#endif
+
+#ifdef EBADF
+ ngx_js_errno_case(EBADF);
+#endif
+
+#ifdef EBADMSG
+ ngx_js_errno_case(EBADMSG);
+#endif
+
+#ifdef EBUSY
+ ngx_js_errno_case(EBUSY);
+#endif
+
+#ifdef ECANCELED
+ ngx_js_errno_case(ECANCELED);
+#endif
+
+#ifdef ECHILD
+ ngx_js_errno_case(ECHILD);
+#endif
+
+#ifdef ECONNABORTED
+ ngx_js_errno_case(ECONNABORTED);
+#endif
+
+#ifdef ECONNREFUSED
+ ngx_js_errno_case(ECONNREFUSED);
+#endif
+
+#ifdef ECONNRESET
+ ngx_js_errno_case(ECONNRESET);
+#endif
+
+#ifdef EDEADLK
+ ngx_js_errno_case(EDEADLK);
+#endif
+
+#ifdef EDESTADDRREQ
+ ngx_js_errno_case(EDESTADDRREQ);
+#endif
+
+#ifdef EDOM
+ ngx_js_errno_case(EDOM);
+#endif
+
+#ifdef EDQUOT
+ ngx_js_errno_case(EDQUOT);
+#endif
+
+#ifdef EEXIST
+ ngx_js_errno_case(EEXIST);
+#endif
+
+#ifdef EFAULT
+ ngx_js_errno_case(EFAULT);
+#endif
+
+#ifdef EFBIG
+ ngx_js_errno_case(EFBIG);
+#endif
+
+#ifdef EHOSTUNREACH
+ ngx_js_errno_case(EHOSTUNREACH);
+#endif
+
+#ifdef EIDRM
+ ngx_js_errno_case(EIDRM);
+#endif
+
+#ifdef EILSEQ
+ ngx_js_errno_case(EILSEQ);
+#endif
+
+#ifdef EINPROGRESS
+ ngx_js_errno_case(EINPROGRESS);
+#endif
+
+#ifdef EINTR
+ ngx_js_errno_case(EINTR);
+#endif
+
+#ifdef EINVAL
+ ngx_js_errno_case(EINVAL);
+#endif
+
+#ifdef EIO
+ ngx_js_errno_case(EIO);
+#endif
+
+#ifdef EISCONN
+ ngx_js_errno_case(EISCONN);
+#endif
+
+#ifdef EISDIR
+ ngx_js_errno_case(EISDIR);
+#endif
+
+#ifdef ELOOP
+ ngx_js_errno_case(ELOOP);
+#endif
+
+#ifdef EMFILE
+ ngx_js_errno_case(EMFILE);
+#endif
+
+#ifdef EMLINK
+ ngx_js_errno_case(EMLINK);
+#endif
+
+#ifdef EMSGSIZE
+ ngx_js_errno_case(EMSGSIZE);
+#endif
+
+#ifdef EMULTIHOP
+ ngx_js_errno_case(EMULTIHOP);
+#endif
+
+#ifdef ENAMETOOLONG
+ ngx_js_errno_case(ENAMETOOLONG);
+#endif
+
+#ifdef ENETDOWN
+ ngx_js_errno_case(ENETDOWN);
+#endif
+
+#ifdef ENETRESET
+ ngx_js_errno_case(ENETRESET);
+#endif
+
+#ifdef ENETUNREACH
+ ngx_js_errno_case(ENETUNREACH);
+#endif
+
+#ifdef ENFILE
+ ngx_js_errno_case(ENFILE);
+#endif
+
+#ifdef ENOBUFS
+ ngx_js_errno_case(ENOBUFS);
+#endif
+
+#ifdef ENODATA
+ ngx_js_errno_case(ENODATA);
+#endif
+
+#ifdef ENODEV
+ ngx_js_errno_case(ENODEV);
+#endif
+
+#ifdef ENOENT
+ ngx_js_errno_case(ENOENT);
+#endif
+
+#ifdef ENOEXEC
+ ngx_js_errno_case(ENOEXEC);
+#endif
+
+#ifdef ENOLINK
+ ngx_js_errno_case(ENOLINK);
+#endif
+
+#ifdef ENOLCK
+#if ENOLINK != ENOLCK
+ ngx_js_errno_case(ENOLCK);
+#endif
+#endif
+
+#ifdef ENOMEM
+ ngx_js_errno_case(ENOMEM);
+#endif
+
+#ifdef ENOMSG
+ ngx_js_errno_case(ENOMSG);
+#endif
+
+#ifdef ENOPROTOOPT
+ ngx_js_errno_case(ENOPROTOOPT);
+#endif
+
+#ifdef ENOSPC
+ ngx_js_errno_case(ENOSPC);
+#endif
+
+#ifdef ENOSR
+ ngx_js_errno_case(ENOSR);
+#endif
+
+#ifdef ENOSTR
+ ngx_js_errno_case(ENOSTR);
+#endif
+
+#ifdef ENOSYS
+ ngx_js_errno_case(ENOSYS);
+#endif
+
+#ifdef ENOTCONN
+ ngx_js_errno_case(ENOTCONN);
+#endif
+
+#ifdef ENOTDIR
+ ngx_js_errno_case(ENOTDIR);
+#endif
+
+#ifdef ENOTEMPTY
+#if ENOTEMPTY != EEXIST
+ ngx_js_errno_case(ENOTEMPTY);
+#endif
+#endif
+
+#ifdef ENOTSOCK
+ ngx_js_errno_case(ENOTSOCK);
+#endif
+
+#ifdef ENOTSUP
+ ngx_js_errno_case(ENOTSUP);
+#else
+#ifdef EOPNOTSUPP
+ ngx_js_errno_case(EOPNOTSUPP);
+#endif
+#endif
+
+#ifdef ENOTTY
+ ngx_js_errno_case(ENOTTY);
+#endif
+
+#ifdef ENXIO
+ ngx_js_errno_case(ENXIO);
+#endif
+
+#ifdef EOVERFLOW
+ ngx_js_errno_case(EOVERFLOW);
+#endif
+
+#ifdef EPERM
+ ngx_js_errno_case(EPERM);
+#endif
+
+#ifdef EPIPE
+ ngx_js_errno_case(EPIPE);
+#endif
+
+#ifdef EPROTO
+ ngx_js_errno_case(EPROTO);
+#endif
+
+#ifdef EPROTONOSUPPORT
+ ngx_js_errno_case(EPROTONOSUPPORT);
+#endif
+
+#ifdef EPROTOTYPE
+ ngx_js_errno_case(EPROTOTYPE);
+#endif
+
+#ifdef ERANGE
+ ngx_js_errno_case(ERANGE);
+#endif
+
+#ifdef EROFS
+ ngx_js_errno_case(EROFS);
+#endif
+
+#ifdef ESPIPE
+ ngx_js_errno_case(ESPIPE);
+#endif
+
+#ifdef ESRCH
+ ngx_js_errno_case(ESRCH);
+#endif
+
+#ifdef ESTALE
+ ngx_js_errno_case(ESTALE);
+#endif
+
+#ifdef ETIME
+ ngx_js_errno_case(ETIME);
+#endif
+
+#ifdef ETIMEDOUT
+ ngx_js_errno_case(ETIMEDOUT);
+#endif
+
+#ifdef ETXTBSY
+ ngx_js_errno_case(ETXTBSY);
+#endif
+
+#ifdef EXDEV
+ ngx_js_errno_case(EXDEV);
+#endif
+
+ default:
+ break;
+ }
+
+ return "UNKNOWN CODE";
+}
+
+
ngx_js_queue_t *
ngx_js_queue_create(ngx_pool_t *pool, ngx_uint_t capacity)
{
diff --git a/nginx/ngx_js.h b/nginx/ngx_js.h
index 8b6fbc85..8319dc85 100644
--- a/nginx/ngx_js.h
+++ b/nginx/ngx_js.h
@@ -412,6 +412,7 @@ njs_int_t ngx_js_ext_flags(njs_vm_t *vm, njs_object_prop_t *prop,

ngx_int_t ngx_js_string(njs_vm_t *vm, njs_value_t *value, njs_str_t *str);
ngx_int_t ngx_js_integer(njs_vm_t *vm, njs_value_t *value, ngx_int_t *n);
+const char *ngx_js_errno_string(int errnum);

ngx_js_queue_t *ngx_js_queue_create(ngx_pool_t *pool, ngx_uint_t capacity);
ngx_int_t ngx_js_queue_push(ngx_js_queue_t *queue, void *item);
diff --git a/src/njs.h b/src/njs.h
index 466932d8..14a245af 100644
--- a/src/njs.h
+++ b/src/njs.h
@@ -72,6 +72,8 @@ extern const njs_value_t njs_value_undefined;
njs_vm_error2(vm, 2, fmt, ##__VA_ARGS__)
#define njs_vm_range_error(vm, fmt, ...) \
njs_vm_error2(vm, 3, fmt, ##__VA_ARGS__)
+#define njs_vm_ref_error(vm, fmt, ...) \
+ njs_vm_error2(vm, 4, fmt, ##__VA_ARGS__)
#define njs_vm_syntax_error(vm, fmt, ...) \
njs_vm_error2(vm, 5, fmt, ##__VA_ARGS__)
#define njs_vm_type_error(vm, fmt, ...) \
diff --git a/src/njs_module.c b/src/njs_module.c
index 859d96a8..5d9c96ae 100644
--- a/src/njs_module.c
+++ b/src/njs_module.c
@@ -148,7 +148,7 @@ njs_module_require(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,

module = njs_module_find(vm, &name, 0);
if (njs_slow_path(module == NULL)) {
- njs_error(vm, "Cannot find module \"%V\"", &name);
+ njs_error(vm, "Cannot load module \"%V\"", &name);

return NJS_ERROR;
}
diff --git a/src/njs_parser.c b/src/njs_parser.c
index 7eb6292e..1f16336f 100644
--- a/src/njs_parser.c
+++ b/src/njs_parser.c
@@ -8114,7 +8114,7 @@ njs_parser_module(njs_parser_t *parser, njs_str_t *name)
vm = parser->vm;

if (name->length == 0) {
- njs_parser_syntax_error(parser, "Cannot find module \"%V\"", name);
+ njs_parser_ref_error(parser, "Cannot load module \"%V\"", name);
return NULL;
}

@@ -8124,13 +8124,16 @@ njs_parser_module(njs_parser_t *parser, njs_str_t *name)
}

if (vm->module_loader == NULL) {
- njs_parser_syntax_error(parser, "Cannot load module \"%V\"", name);
+ njs_parser_ref_error(parser, "Module loader callback is not provided");
return NULL;
}

module = vm->module_loader(vm, vm->module_loader_opaque, name);
if (module == NULL) {
- njs_parser_syntax_error(parser, "Cannot find module \"%V\"", name);
+ if (!njs_is_valid(&vm->exception)) {
+ njs_parser_ref_error(parser, "Cannot load module \"%V\"", name);
+ }
+
return NULL;
}

diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c
index c52753a7..c4dc6dde 100644
--- a/src/test/njs_unit_test.c
+++ b/src/test/njs_unit_test.c
@@ -18975,7 +18975,7 @@ static njs_unit_test_t njs_test[] =
/* require(). */

{ njs_str("require('unknown_module')"),
- njs_str("Error: Cannot find module \"unknown_module\"") },
+ njs_str("Error: Cannot load module \"unknown_module\"") },

{ njs_str("require()"),
njs_str("TypeError: missing path") },
@@ -19045,7 +19045,7 @@ static njs_unit_test_t njs_test[] =
njs_str("SyntaxError: Unexpected token \"{\" in 1") },

{ njs_str("import x from ''"),
- njs_str("SyntaxError: Cannot find module \"\" in 1") },
+ njs_str("ReferenceError: Cannot load module \"\" in 1") },

{ njs_str("export"),
njs_str("SyntaxError: Illegal export statement in 1") },
diff --git a/test/shell_test_njs.exp b/test/shell_test_njs.exp
index 52ce4886..fac0fe3a 100644
--- a/test/shell_test_njs.exp
+++ b/test/shell_test_njs.exp
@@ -173,13 +173,13 @@ njs_test {
# quiet mode

njs_run {"-q" "test/js/import_chain.t.js"} \
- "SyntaxError: Cannot find module \"lib2.js\" in 7"
+ "ReferenceError: Cannot load module \"lib2.js\" in 7"

# sandboxing

njs_test {
{"var fs = require('fs')\r\n"
- "Error: Cannot find module \"fs\"\r\n"}
+ "Error: Cannot load module \"fs\"\r\n"}
} "-s"

njs_test {
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[njs] Improved error messages for module loading failures.

Anonymous User 201 October 21, 2024 09:08PM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 250
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 500 on July 15, 2024
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready