Skip to content

Commit

Permalink
Improved error messages for module loading failures.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
xeioex committed Oct 22, 2024
1 parent 1b2a339 commit ed36e94
Show file tree
Hide file tree
Showing 7 changed files with 362 additions and 10 deletions.
350 changes: 348 additions & 2 deletions nginx/ngx_js.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
{
Expand Down
1 change: 1 addition & 0 deletions nginx/ngx_js.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/njs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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, ...) \
Expand Down
Loading

0 comments on commit ed36e94

Please sign in to comment.