From 64cd10254627fa7db2d44f0494703009e05703b5 Mon Sep 17 00:00:00 2001 From: Andrei Belov Date: Mon, 29 Oct 2018 14:24:26 +0300 Subject: Docker: avoid removing of Ruby dependencies. This closes #179 issue on GitHub. --- pkg/docker/Dockerfile.full | 2 +- pkg/docker/Dockerfile.go1.7-dev | 2 +- pkg/docker/Dockerfile.go1.8-dev | 2 +- pkg/docker/Dockerfile.minimal | 2 +- pkg/docker/Dockerfile.perl5.24 | 2 +- pkg/docker/Dockerfile.php7.0 | 2 +- pkg/docker/Dockerfile.python2.7 | 2 +- pkg/docker/Dockerfile.python3.5 | 2 +- pkg/docker/Dockerfile.ruby2.3 | 2 +- pkg/docker/Dockerfile.tmpl | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/docker/Dockerfile.full b/pkg/docker/Dockerfile.full index 2ccfc16c..118a9a96 100644 --- a/pkg/docker/Dockerfile.full +++ b/pkg/docker/Dockerfile.full @@ -73,7 +73,7 @@ RUN set -x \ && apt-get install --no-install-recommends --no-install-suggests -y \ $unitPackages \ curl \ - && apt-get remove --purge --auto-remove -y apt-transport-https ca-certificates && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ + && apt-get remove --purge --auto-remove -y apt-transport-https && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ \ # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) && if [ -n "$tempDir" ]; then \ diff --git a/pkg/docker/Dockerfile.go1.7-dev b/pkg/docker/Dockerfile.go1.7-dev index aa915518..c39d8f04 100644 --- a/pkg/docker/Dockerfile.go1.7-dev +++ b/pkg/docker/Dockerfile.go1.7-dev @@ -73,7 +73,7 @@ RUN set -x \ && apt-get install --no-install-recommends --no-install-suggests -y \ $unitPackages \ curl \ - && apt-get remove --purge --auto-remove -y apt-transport-https ca-certificates && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ + && apt-get remove --purge --auto-remove -y apt-transport-https && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ \ # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) && if [ -n "$tempDir" ]; then \ diff --git a/pkg/docker/Dockerfile.go1.8-dev b/pkg/docker/Dockerfile.go1.8-dev index e623182b..0db00501 100644 --- a/pkg/docker/Dockerfile.go1.8-dev +++ b/pkg/docker/Dockerfile.go1.8-dev @@ -73,7 +73,7 @@ RUN set -x \ && apt-get install --no-install-recommends --no-install-suggests -y \ $unitPackages \ curl \ - && apt-get remove --purge --auto-remove -y apt-transport-https ca-certificates && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ + && apt-get remove --purge --auto-remove -y apt-transport-https && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ \ # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) && if [ -n "$tempDir" ]; then \ diff --git a/pkg/docker/Dockerfile.minimal b/pkg/docker/Dockerfile.minimal index 0ff59411..b6735b15 100644 --- a/pkg/docker/Dockerfile.minimal +++ b/pkg/docker/Dockerfile.minimal @@ -73,7 +73,7 @@ RUN set -x \ && apt-get install --no-install-recommends --no-install-suggests -y \ $unitPackages \ curl \ - && apt-get remove --purge --auto-remove -y apt-transport-https ca-certificates && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ + && apt-get remove --purge --auto-remove -y apt-transport-https && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ \ # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) && if [ -n "$tempDir" ]; then \ diff --git a/pkg/docker/Dockerfile.perl5.24 b/pkg/docker/Dockerfile.perl5.24 index 06067fc7..bb27e721 100644 --- a/pkg/docker/Dockerfile.perl5.24 +++ b/pkg/docker/Dockerfile.perl5.24 @@ -73,7 +73,7 @@ RUN set -x \ && apt-get install --no-install-recommends --no-install-suggests -y \ $unitPackages \ curl \ - && apt-get remove --purge --auto-remove -y apt-transport-https ca-certificates && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ + && apt-get remove --purge --auto-remove -y apt-transport-https && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ \ # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) && if [ -n "$tempDir" ]; then \ diff --git a/pkg/docker/Dockerfile.php7.0 b/pkg/docker/Dockerfile.php7.0 index a6b816bf..fef46c83 100644 --- a/pkg/docker/Dockerfile.php7.0 +++ b/pkg/docker/Dockerfile.php7.0 @@ -73,7 +73,7 @@ RUN set -x \ && apt-get install --no-install-recommends --no-install-suggests -y \ $unitPackages \ curl \ - && apt-get remove --purge --auto-remove -y apt-transport-https ca-certificates && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ + && apt-get remove --purge --auto-remove -y apt-transport-https && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ \ # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) && if [ -n "$tempDir" ]; then \ diff --git a/pkg/docker/Dockerfile.python2.7 b/pkg/docker/Dockerfile.python2.7 index b02fe194..d02ef003 100644 --- a/pkg/docker/Dockerfile.python2.7 +++ b/pkg/docker/Dockerfile.python2.7 @@ -73,7 +73,7 @@ RUN set -x \ && apt-get install --no-install-recommends --no-install-suggests -y \ $unitPackages \ curl \ - && apt-get remove --purge --auto-remove -y apt-transport-https ca-certificates && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ + && apt-get remove --purge --auto-remove -y apt-transport-https && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ \ # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) && if [ -n "$tempDir" ]; then \ diff --git a/pkg/docker/Dockerfile.python3.5 b/pkg/docker/Dockerfile.python3.5 index 32ecfcf5..67c7e3d6 100644 --- a/pkg/docker/Dockerfile.python3.5 +++ b/pkg/docker/Dockerfile.python3.5 @@ -73,7 +73,7 @@ RUN set -x \ && apt-get install --no-install-recommends --no-install-suggests -y \ $unitPackages \ curl \ - && apt-get remove --purge --auto-remove -y apt-transport-https ca-certificates && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ + && apt-get remove --purge --auto-remove -y apt-transport-https && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ \ # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) && if [ -n "$tempDir" ]; then \ diff --git a/pkg/docker/Dockerfile.ruby2.3 b/pkg/docker/Dockerfile.ruby2.3 index ce5fefda..93792864 100644 --- a/pkg/docker/Dockerfile.ruby2.3 +++ b/pkg/docker/Dockerfile.ruby2.3 @@ -73,7 +73,7 @@ RUN set -x \ && apt-get install --no-install-recommends --no-install-suggests -y \ $unitPackages \ curl \ - && apt-get remove --purge --auto-remove -y apt-transport-https ca-certificates && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ + && apt-get remove --purge --auto-remove -y apt-transport-https && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ \ # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) && if [ -n "$tempDir" ]; then \ diff --git a/pkg/docker/Dockerfile.tmpl b/pkg/docker/Dockerfile.tmpl index 76722f88..18d6d34e 100644 --- a/pkg/docker/Dockerfile.tmpl +++ b/pkg/docker/Dockerfile.tmpl @@ -73,7 +73,7 @@ RUN set -x \ && apt-get install --no-install-recommends --no-install-suggests -y \ $unitPackages \ curl \ - && apt-get remove --purge --auto-remove -y apt-transport-https ca-certificates && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ + && apt-get remove --purge --auto-remove -y apt-transport-https && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unit.list \ \ # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) && if [ -n "$tempDir" ]; then \ -- cgit From 3b0afb16814353a5d34a7384f4e84e9c17f3fb8e Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Wed, 31 Oct 2018 16:31:14 +0300 Subject: Version bump. --- src/nxt_main.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nxt_main.h b/src/nxt_main.h index 670010f8..12c0ce6d 100644 --- a/src/nxt_main.h +++ b/src/nxt_main.h @@ -11,8 +11,8 @@ #include -#define NXT_VERSION "1.5" -#define NXT_VERNUM 10500 +#define NXT_VERSION "1.6" +#define NXT_VERNUM 10600 #define NXT_SERVER "Unit/" NXT_VERSION -- cgit From c838c3bd1580735e8020687f94e6307f13aba156 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Wed, 31 Oct 2018 15:51:51 +0300 Subject: Node.js: added async request execution. --- src/nodejs/unit-http/http_server.js | 29 ++++- src/nodejs/unit-http/unit.cpp | 227 +++++++++++++++++++++++------------- src/nodejs/unit-http/unit.h | 8 +- src/nxt_unit.c | 3 +- src/nxt_unit.h | 2 + 5 files changed, 176 insertions(+), 93 deletions(-) diff --git a/src/nodejs/unit-http/http_server.js b/src/nodejs/unit-http/http_server.js index fa7b8e9b..ddacb420 100755 --- a/src/nodejs/unit-http/http_server.js +++ b/src/nodejs/unit-http/http_server.js @@ -232,7 +232,6 @@ ServerResponse.prototype.write = function write(chunk, encoding, callback) { ServerResponse.prototype.end = function end(chunk, encoding, callback) { this._writeBody(chunk, encoding, callback); - unit_lib.unit_response_end(this) this.finished = true; @@ -290,10 +289,10 @@ function Server(requestListener) { EventEmitter.call(this); this.unit = new unit_lib.Unit(); - this.unit.createServer(); - this.unit.server = this; + this.unit.createServer(); + this.socket = Socket; this.request = ServerRequest; this.response = ServerResponse; @@ -318,10 +317,32 @@ Server.prototype.listen = function () { this.unit.listen(); }; +Server.prototype.run_events = function (server, req, res) { + /* Important!!! setImmediate starts the next iteration in Node.js loop. */ + setImmediate(function () { + server.emit("request", req, res); + + Promise.resolve().then(() => { + let buf = server.unit._read(req.socket.req_pointer); + + if (buf.length != 0) { + req.emit("data", buf); + } + + req.emit("end"); + }); + + Promise.resolve().then(() => { + if (res.finished) { + unit_lib.unit_response_end(res); + } + }); + }); +}; + function connectionListener(socket) { } - module.exports = { STATUS_CODES: http.STATUS_CODES, Server, diff --git a/src/nodejs/unit-http/unit.cpp b/src/nodejs/unit-http/unit.cpp index 40f641a6..5d7f15c0 100644 --- a/src/nodejs/unit-http/unit.cpp +++ b/src/nodejs/unit-http/unit.cpp @@ -5,6 +5,11 @@ #include "unit.h" +#include +#include + +#include + napi_ref Unit::constructor_; @@ -31,11 +36,12 @@ Unit::init(napi_env env, napi_value exports) napi_property_descriptor properties[] = { { "createServer", 0, create_server, 0, 0, 0, napi_default, 0 }, - { "listen", 0, listen, 0, 0, 0, napi_default, 0 } + { "listen", 0, listen, 0, 0, 0, napi_default, 0 }, + { "_read", 0, _read, 0, 0, 0, napi_default, 0 } }; status = napi_define_class(env, "Unit", NAPI_AUTO_LENGTH, create, nullptr, - 2, properties, &cons); + 3, properties, &cons); if (status != napi_ok) { goto failed; } @@ -158,14 +164,13 @@ Unit::create_server(napi_env env, napi_callback_info info) { Unit *obj; size_t argc; - napi_value jsthis; + napi_value jsthis, argv; napi_status status; - napi_value argv[1]; nxt_unit_init_t unit_init; argc = 1; - status = napi_get_cb_info(env, info, &argc, argv, &jsthis, nullptr); + status = napi_get_cb_info(env, info, &argc, &argv, &jsthis, nullptr); if (status != napi_ok) { goto failed; } @@ -179,6 +184,8 @@ Unit::create_server(napi_env env, napi_callback_info info) unit_init.data = obj; unit_init.callbacks.request_handler = request_handler; + unit_init.callbacks.add_port = add_port; + unit_init.callbacks.remove_port = remove_port; obj->unit_ctx_ = nxt_unit_init(&unit_init); if (obj->unit_ctx_ == NULL) { @@ -198,41 +205,53 @@ failed: napi_value Unit::listen(napi_env env, napi_callback_info info) { - int ret; - Unit *obj; - napi_value jsthis; - napi_status status; + return nullptr; +} + + +napi_value +Unit::_read(napi_env env, napi_callback_info info) +{ + Unit *obj; + void *data; + size_t argc; + int64_t req_pointer; + napi_value jsthis, buffer, argv; + napi_status status; + nxt_unit_request_info_t *req; + + argc = 1; - status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr); + status = napi_get_cb_info(env, info, &argc, &argv, &jsthis, nullptr); if (status != napi_ok) { - goto failed; + napi_throw_error(env, NULL, "Failed to get arguments from js"); + return nullptr; } status = napi_unwrap(env, jsthis, reinterpret_cast(&obj)); if (status != napi_ok) { - goto failed; - } - - if (obj->unit_ctx_ == NULL) { - napi_throw_error(env, NULL, "Unit context was not created"); + napi_throw_error(env, NULL, "Failed to get Unit object form js"); return nullptr; } - ret = nxt_unit_run(obj->unit_ctx_); - if (ret != NXT_UNIT_OK) { - napi_throw_error(env, NULL, "Failed to run Unit"); + status = napi_get_value_int64(env, argv, &req_pointer); + if (status != napi_ok) { + napi_throw_error(env, NULL, "Failed to get request pointer"); return nullptr; } - nxt_unit_done(obj->unit_ctx_); - - return nullptr; + req = (nxt_unit_request_info_t *) (uintptr_t) req_pointer; -failed: + status = napi_create_buffer(env, (size_t) req->content_length, + &data, &buffer); + if (status != napi_ok) { + napi_throw_error(env, NULL, "Failed to create request buffer"); + return nullptr; + } - napi_throw_error(env, NULL, "Failed to listen Unit socket"); + nxt_unit_request_read(req, data, req->content_length); - return nullptr; + return buffer; } @@ -242,8 +261,9 @@ Unit::request_handler(nxt_unit_request_info_t *req) Unit *obj; napi_value socket, request, response; napi_value global, server_obj; - napi_value req_argv[3]; + napi_value run_events, events_res; napi_status status; + napi_value events_args[3]; obj = reinterpret_cast(req->unit->data); @@ -284,73 +304,126 @@ Unit::request_handler(nxt_unit_request_info_t *req) return; } - req_argv[1] = request; - req_argv[2] = response; - status = obj->create_headers(req, request); if (status != napi_ok) { napi_throw_error(obj->env_, NULL, "Failed to create headers"); return; } - obj->emit(server_obj, "request", sizeof("request") - 1, 3, req_argv); - obj->emit_post_data(request, req); + status = napi_get_named_property(obj->env_, server_obj, "run_events", + &run_events); + if (status != napi_ok) { + napi_throw_error(obj->env_, NULL, "Failed to get" + " 'run_events' function"); + return; + } + + events_args[0] = server_obj; + events_args[1] = request; + events_args[2] = response; + + status = napi_call_function(obj->env_, server_obj, run_events, 3, + events_args, &events_res); + if (status != napi_ok) { + napi_throw_error(obj->env_, NULL, "Failed to call" + " 'run_events' function"); + return; + } napi_close_handle_scope(obj->env_, scope); } -napi_value -Unit::get_server_object() +void +nxt_uv_read_callback(uv_poll_t *handle, int status, int events) { - napi_value unit_obj, server_obj; + nxt_unit_run_once((nxt_unit_ctx_t *) handle->data); +} + + +int +Unit::add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) +{ + int err; + Unit *obj; + uv_loop_t *loop; + uv_poll_t *uv_handle; napi_status status; - status = napi_get_reference_value(env_, wrapper_, &unit_obj); - if (status != napi_ok) { - return nullptr; - } + if (port->in_fd != -1) { + obj = reinterpret_cast(ctx->unit->data); - status = napi_get_named_property(env_, unit_obj, "server", &server_obj); - if (status != napi_ok) { - return nullptr; + if (fcntl(port->in_fd, F_SETFL, O_NONBLOCK) == -1) { + napi_throw_error(obj->env_, NULL, "Failed to upgrade read" + " file descriptor to O_NONBLOCK"); + return -1; + } + + status = napi_get_uv_event_loop(obj->env_, &loop); + if (status != napi_ok) { + napi_throw_error(obj->env_, NULL, "Failed to get uv.loop"); + return NXT_UNIT_ERROR; + } + + uv_handle = new uv_poll_t; + + err = uv_poll_init(loop, uv_handle, port->in_fd); + if (err < 0) { + napi_throw_error(obj->env_, NULL, "Failed to init uv.poll"); + return NXT_UNIT_ERROR; + } + + err = uv_poll_start(uv_handle, UV_READABLE, nxt_uv_read_callback); + if (err < 0) { + napi_throw_error(obj->env_, NULL, "Failed to start uv.poll"); + return NXT_UNIT_ERROR; + } + + port->data = uv_handle; + uv_handle->data = ctx; } - return server_obj; + return nxt_unit_add_port(ctx, port); } -napi_value -Unit::emit(napi_value obj, const char *name, size_t name_len, size_t argc, - napi_value *argv) +void +Unit::remove_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id) { - napi_value emitter, return_val, str; - napi_status status; + nxt_unit_port_t *port; - status = napi_get_named_property(env_, obj, "emit", &emitter); - if (status != napi_ok) { - return nullptr; + port = nxt_unit_find_port(ctx, port_id); + if (port == NULL) { + return; } - status = napi_create_string_latin1(env_, name, name_len, &str); - if (status != napi_ok) { - return nullptr; + if (port->in_fd != -1 && port->data != NULL) { + uv_poll_stop((uv_poll_t *) port->data); + + delete (uv_poll_t *) port->data; } - if (argc != 0) { - argv[0] = str; + nxt_unit_remove_port(ctx, port_id); +} - } else { - argc = 1; - argv = &str; + +napi_value +Unit::get_server_object() +{ + napi_value unit_obj, server_obj; + napi_status status; + + status = napi_get_reference_value(env_, wrapper_, &unit_obj); + if (status != napi_ok) { + return nullptr; } - status = napi_call_function(env_, obj, emitter, argc, argv, &return_val); + status = napi_get_named_property(env_, unit_obj, "server", &server_obj); if (status != napi_ok) { return nullptr; } - return return_val; + return server_obj; } @@ -480,7 +553,7 @@ Unit::append_header(nxt_unit_field_t *f, napi_value headers, napi_value Unit::create_socket(napi_value server_obj, nxt_unit_request_info_t *req) { - napi_value constructor, return_val; + napi_value constructor, return_val, req_pointer; napi_status status; status = napi_get_named_property(env_, server_obj, "socket", @@ -494,6 +567,17 @@ Unit::create_socket(napi_value server_obj, nxt_unit_request_info_t *req) return nullptr; } + status = napi_create_int64(env_, (uintptr_t) req, &req_pointer); + if (status != napi_ok) { + return nullptr; + } + + status = napi_set_named_property(env_, return_val, "req_pointer", + req_pointer); + if (status != napi_ok) { + return nullptr; + } + return return_val; } @@ -563,27 +647,6 @@ Unit::create_response(napi_value server_obj, napi_value socket, } -void -Unit::emit_post_data(napi_value request, nxt_unit_request_info_t *req) -{ - void *data; - napi_value req_argv[2]; - napi_status status; - - status = napi_create_buffer(env_, (size_t) req->content_length, - &data, &req_argv[1]); - if (status != napi_ok) { - napi_throw_error(env_, NULL, "Failed to create request buffer"); - return; - } - - nxt_unit_request_read(req, data, req->content_length); - - emit(request, "data", sizeof("data") - 1, 2, req_argv); - emit(request, "end", sizeof("end") - 1, 0, nullptr); -} - - napi_value Unit::response_send_headers(napi_env env, napi_callback_info info) { diff --git a/src/nodejs/unit-http/unit.h b/src/nodejs/unit-http/unit.h index 753a14d8..90c67efc 100644 --- a/src/nodejs/unit-http/unit.h +++ b/src/nodejs/unit-http/unit.h @@ -36,13 +36,13 @@ private: static napi_value create_server(napi_env env, napi_callback_info info); static napi_value listen(napi_env env, napi_callback_info info); + static napi_value _read(napi_env env, napi_callback_info info); static void request_handler(nxt_unit_request_info_t *req); + static int add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port); + static void remove_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id); napi_value get_server_object(); - napi_value emit(napi_value obj, const char *name, size_t name_len, - size_t argc, napi_value *argv); - napi_value create_socket(napi_value server_obj, nxt_unit_request_info_t *req); @@ -52,8 +52,6 @@ private: napi_value request, nxt_unit_request_info_t *req, Unit *obj); - void emit_post_data(napi_value request, nxt_unit_request_info_t *req); - static napi_value response_send_headers(napi_env env, napi_callback_info info); diff --git a/src/nxt_unit.c b/src/nxt_unit.c index 0d1be557..24e51075 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -74,7 +74,6 @@ static nxt_unit_process_t *nxt_unit_process_get(nxt_unit_ctx_t *ctx, static nxt_unit_process_t *nxt_unit_process_find(nxt_unit_ctx_t *ctx, pid_t pid, int remove); static nxt_unit_process_t *nxt_unit_process_pop_first(nxt_unit_impl_t *lib); -static int nxt_unit_run_once(nxt_unit_ctx_t *ctx); static int nxt_unit_create_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id, int *fd); @@ -2697,7 +2696,7 @@ nxt_unit_run(nxt_unit_ctx_t *ctx) } -static int +int nxt_unit_run_once(nxt_unit_ctx_t *ctx) { int rc; diff --git a/src/nxt_unit.h b/src/nxt_unit.h index 1b4923a2..2806d035 100644 --- a/src/nxt_unit.h +++ b/src/nxt_unit.h @@ -196,6 +196,8 @@ int nxt_unit_process_msg(nxt_unit_ctx_t *, nxt_unit_port_id_t *port_id, */ int nxt_unit_run(nxt_unit_ctx_t *); +int nxt_unit_run_once(nxt_unit_ctx_t *ctx); + /* Destroy application library object. */ void nxt_unit_done(nxt_unit_ctx_t *); -- cgit From 7a06fab9e32ca3ba91a566b065188c0b112d6c09 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Thu, 1 Nov 2018 17:02:46 +0300 Subject: Mention of "nodejs" configure option in help. --- auto/help | 3 +++ 1 file changed, 3 insertions(+) diff --git a/auto/help b/auto/help index 91be220f..f22362d5 100644 --- a/auto/help +++ b/auto/help @@ -55,4 +55,7 @@ cat << END ruby OPTIONS configure Ruby module run "./configure ruby --help" to see available options + nodejs OPTIONS configure Node.js module + run "./configure nodejs --help" to see available options + END -- cgit From b7442743cfdf52185f293c770a883f1467776c5e Mon Sep 17 00:00:00 2001 From: Andrey Zelenkov Date: Thu, 1 Nov 2018 19:10:32 +0300 Subject: Node.js: fixed typo in naming rawHeaders() method of request. --- src/nodejs/unit-http/unit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nodejs/unit-http/unit.cpp b/src/nodejs/unit-http/unit.cpp index 5d7f15c0..97238834 100644 --- a/src/nodejs/unit-http/unit.cpp +++ b/src/nodejs/unit-http/unit.cpp @@ -464,7 +464,7 @@ Unit::create_headers(nxt_unit_request_info_t *req, napi_value request) return status; } - status = napi_set_named_property(env_, request, "raw_headers", raw_headers); + status = napi_set_named_property(env_, request, "rawHeaders", raw_headers); if (status != napi_ok) { return status; } -- cgit From 4a77c447babd494b66156c43796deabaa47697a3 Mon Sep 17 00:00:00 2001 From: Andrey Zelenkov Date: Tue, 6 Nov 2018 19:04:01 +0300 Subject: Node.js: socket.js improvements. - Fixed handling of the "options" parameter in Socket() constructor; - Now the connect() method returns "this"; - Deduplicated the address() method; - Added missing "callback" argument to the end() method; - Now the destroy() method returns "this"; - Added "timeout" argument type check in the setTimeout() method. --- src/nodejs/unit-http/socket.js | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/nodejs/unit-http/socket.js b/src/nodejs/unit-http/socket.js index 89702834..aef065bf 100755 --- a/src/nodejs/unit-http/socket.js +++ b/src/nodejs/unit-http/socket.js @@ -12,15 +12,16 @@ const unit_lib = require('unit-http/build/Release/unit-http.node'); function Socket(options) { EventEmitter.call(this); - if (typeof options === 'number') { - options = { fd: options }; + options = options || {}; - } else if (options === undefined) { - options = {}; + if (typeof options !== 'object') { + throw new TypeError('Options must be object'); } - this.readable = options.readable !== false; - this.writable = options.writable !== false; + this.readable = (typeof options.readable === 'boolean' ? options.readable + : false); + this.writable = (typeof options.writable === 'boolean' ? options.writable + : false); } util.inherits(Socket, EventEmitter); @@ -38,25 +39,24 @@ Socket.prototype.remotePort = 0; Socket.prototype.address = function address() { }; -Socket.prototype.connect = function connect(options, callback) { - if (callback !== null) { - this.once('connect', cb); - } +Socket.prototype.connect = function connect(options, connectListener) { + this.once('connect', connectListener); this.connecting = true; this.writable = true; -}; -Socket.prototype.address = function address() { + return this; }; Socket.prototype.destroy = function destroy(exception) { this.connecting = false; this.readable = false; this.writable = false; + + return this; }; -Socket.prototype.end = function end(data, encoding) { +Socket.prototype.end = function end(data, encoding, callback) { }; Socket.prototype.pause = function pause() { @@ -77,13 +77,15 @@ Socket.prototype.setKeepAlive = function setKeepAlive(enable, initialDelay) { Socket.prototype.setNoDelay = function setNoDelay(noDelay) { }; -Socket.prototype.setTimeout = function setTimeout(msecs, callback) { - this.timeout = msecs; - - if (callback) { - this.on('timeout', callback); +Socket.prototype.setTimeout = function setTimeout(timeout, callback) { + if (typeof timeout !== 'number') { + throw new TypeError('Timeout must be number'); } + this.timeout = timeout; + + this.on('timeout', callback); + return this; }; -- cgit From 4f4a2d8c63e55401fe0fccb47d747701cdf3171e Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Sat, 10 Nov 2018 07:38:43 +0300 Subject: Fixed "freed pointer is out of pool" alerts. The issue was caused by misplacement of allocated blocks in rbtree due to broken comparison function if the distance between two allocations did not fit into intptr_t. As the result, nxt_mp_free() could have failed to find the allocation. In particular, it was mostly observed when Unit was compiled with musl C library on 32-bits systems. This closes #118 issue on GitHub. --- src/nxt_mp.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/nxt_mp.c b/src/nxt_mp.c index a0f19ac2..5c1a4d00 100644 --- a/src/nxt_mp.c +++ b/src/nxt_mp.c @@ -768,7 +768,15 @@ nxt_mp_rbtree_compare(nxt_rbtree_node_t *node1, nxt_rbtree_node_t *node2) block1 = (nxt_mp_block_t *) node1; block2 = (nxt_mp_block_t *) node2; - return (uintptr_t) block1->start - (uintptr_t) block2->start; + /* + * Shifting is necessary to prevent overflow of intptr_t when block1->start + * is much greater than block2->start or vice versa. + * + * It is safe to drop one bit since there cannot be adjacent addresses + * because of alignments and allocation sizes. Effectively this reduces + * the absolute values to fit into the magnitude of intptr_t. + */ + return ((uintptr_t) block1->start >> 1) - ((uintptr_t) block2->start >> 1); } -- cgit From ff9bed64da495b6c234bcfa4dcf18932730e58e7 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Tue, 13 Nov 2018 18:43:39 +0300 Subject: Fixed nxt_openssl_chain_file() return type. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This closes #182 issue on GitHub. Thanks to 洪志道 (Hong Zhi Dao). --- src/nxt_openssl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nxt_openssl.c b/src/nxt_openssl.c index 441da54b..401de2de 100644 --- a/src/nxt_openssl.c +++ b/src/nxt_openssl.c @@ -40,7 +40,7 @@ static void nxt_openssl_locks_free(void); #endif static nxt_int_t nxt_openssl_server_init(nxt_task_t *task, nxt_tls_conf_t *conf); -static nxt_uint_t nxt_openssl_chain_file(SSL_CTX *ctx, nxt_fd_t fd); +static nxt_int_t nxt_openssl_chain_file(SSL_CTX *ctx, nxt_fd_t fd); static void nxt_openssl_server_free(nxt_task_t *task, nxt_tls_conf_t *conf); static void nxt_openssl_conn_init(nxt_task_t *task, nxt_tls_conf_t *conf, nxt_conn_t *c); @@ -359,14 +359,14 @@ fail: } -static nxt_uint_t +static nxt_int_t nxt_openssl_chain_file(SSL_CTX *ctx, nxt_fd_t fd) { BIO *bio; X509 *cert, *ca; long reason; EVP_PKEY *key; - nxt_uint_t ret; + nxt_int_t ret; bio = BIO_new(BIO_s_fd()); if (bio == NULL) { -- cgit From 4d7f708b258e9fb4280883b4f64700367dcbb40d Mon Sep 17 00:00:00 2001 From: Andrey Zelenkov Date: Tue, 13 Nov 2018 18:51:55 +0300 Subject: Tests: leave unit.log in case of error or failure. --- test/unit.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/unit.py b/test/unit.py index 98a0a4db..edfa39a0 100644 --- a/test/unit.py +++ b/test/unit.py @@ -25,11 +25,31 @@ class TestUnit(unittest.TestCase): def tearDown(self): self.stop() + # detect errors and failures for current test + + def list2reason(exc_list): + if exc_list and exc_list[-1][0] is self: + return exc_list[-1][1] + + if hasattr(self, '_outcome'): + result = self.defaultTestResult() + self._feedErrorsToResult(result, self._outcome.errors) + else: + result = getattr(self, '_outcomeForDoCleanups', + self._resultForDoCleanups) + + success = not list2reason(result.errors) \ + and not list2reason(result.failures) + + # check unit.log for alerts + with open(self.testdir + '/unit.log', 'r', encoding='utf-8', errors='ignore') as f: self._check_alerts(f.read()) - if '--leave' not in sys.argv: + # remove unit.log + + if '--leave' not in sys.argv and success: shutil.rmtree(self.testdir) def check_modules(self, *modules): -- cgit From cf1f84b67c50156dc371e834bbdfd49c105abb25 Mon Sep 17 00:00:00 2001 From: Andrey Zelenkov Date: Tue, 13 Nov 2018 18:56:18 +0300 Subject: Tests: print path to unit.log file when it was saved. --- test/unit.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/test/unit.py b/test/unit.py index edfa39a0..a5f96968 100644 --- a/test/unit.py +++ b/test/unit.py @@ -52,6 +52,9 @@ class TestUnit(unittest.TestCase): if '--leave' not in sys.argv and success: shutil.rmtree(self.testdir) + else: + self._print_path_to_log() + def check_modules(self, *modules): self._run() @@ -191,11 +194,16 @@ class TestUnit(unittest.TestCase): for skip in self.skip_alerts: alerts = [al for al in alerts if re.search(skip, al) is None] - self.assertFalse(alerts, 'alert(s)') + if alerts: + self._print_path_to_log() + self.assertFalse(alerts, 'alert(s)') if not self.skip_sanitizer: - self.assertFalse(re.findall('.+Sanitizer.+', log), - 'sanitizer error(s)') + sanitizer_errors = re.findall('.+Sanitizer.+', log) + + if sanitizer_errors: + self._print_path_to_log() + self.assertFalse(sanitizer_error, 'sanitizer error(s)') if found: print('skipped.') @@ -219,6 +227,9 @@ class TestUnit(unittest.TestCase): return ret + def _print_path_to_log(self): + print('Path to unit.log:\n' + self.testdir + '/unit.log') + class TestUnitHTTP(TestUnit): def http(self, start_str, **kwargs): -- cgit From 92ddc15a84d50306b3d1e22387dd0373994968af Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Tue, 13 Nov 2018 19:04:48 +0300 Subject: Checking error states in I/O handlers. --- src/nxt_conn_read.c | 4 ++++ src/nxt_openssl.c | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/nxt_conn_read.c b/src/nxt_conn_read.c index e458bf81..8228326b 100644 --- a/src/nxt_conn_read.c +++ b/src/nxt_conn_read.c @@ -48,6 +48,10 @@ nxt_conn_io_read(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "conn read fd:%d rdy:%d cl:%d", c->socket.fd, c->socket.read_ready, c->socket.closed); + if (c->socket.error != 0) { + return; + } + engine = task->thread->engine; /* diff --git a/src/nxt_openssl.c b/src/nxt_openssl.c index 401de2de..99dd2077 100644 --- a/src/nxt_openssl.c +++ b/src/nxt_openssl.c @@ -503,13 +503,19 @@ fail: nxt_inline void -nxt_openssl_conn_free(nxt_task_t *task, nxt_openssl_conn_t *tls) +nxt_openssl_conn_free(nxt_task_t *task, nxt_conn_t *c) { + nxt_openssl_conn_t *tls; + nxt_debug(task, "openssl conn free"); - nxt_free(tls->buffer.start); + tls = c->u.tls; - SSL_free(tls->session); + if (tls != NULL) { + c->u.tls = NULL; + nxt_free(tls->buffer.start); + SSL_free(tls->session); + } } @@ -526,9 +532,20 @@ nxt_openssl_conn_handshake(nxt_task_t *task, void *obj, void *data) const nxt_conn_state_t *state; c = obj; + + nxt_debug(task, "openssl conn handshake fd:%d", c->socket.fd); + + if (c->socket.error != 0) { + return; + } + tls = c->u.tls; - nxt_debug(task, "openssl conn handshake: %d", tls->times); + if (tls == NULL) { + return; + } + + nxt_debug(task, "openssl conn handshake: %d times", tls->times); /* "tls->times == 1" is suitable to run SSL_do_handshake() in job. */ @@ -715,10 +732,19 @@ nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj, void *data) c = obj; - nxt_debug(task, "openssl conn shutdown"); + nxt_debug(task, "openssl conn shutdown fd:%d", c->socket.fd); + + if (c->socket.error != 0) { + return; + } c->read_state = NULL; tls = c->u.tls; + + if (tls == NULL) { + return; + } + s = tls->session; if (s == NULL || !tls->handshake) { @@ -807,7 +833,7 @@ nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj, void *data) done: - nxt_openssl_conn_free(task, tls); + nxt_openssl_conn_free(task, c); nxt_work_queue_add(c->write_work_queue, handler, task, c, data); } -- cgit From 0b558b873add688bd110fb1465585e696438571c Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Wed, 14 Nov 2018 20:01:34 +0300 Subject: Node.js: ./configure script cleanup. --- auto/modules/nodejs | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/auto/modules/nodejs b/auto/modules/nodejs index 56f84876..3138904a 100644 --- a/auto/modules/nodejs +++ b/auto/modules/nodejs @@ -19,9 +19,9 @@ for nxt_option; do --help) cat << END - --node=NAME set node executable - --npm=NAME set npm executable - --node-gyp=NAME set node-gyp executable + --node=FILE set node executable + --npm=FILE set npm executable + --node-gyp=FILE set node-gyp executable END exit 0 @@ -49,13 +49,14 @@ fi . $NXT_AUTOCONF_DATA -$echo "configuring nodejs module" -$echo "configuring nodejs module..." >> $NXT_AUTOCONF_ERR - NXT_NODE=${NXT_NODE=node} NXT_NPM=${NXT_NPM=npm} NXT_NODE_GYP=${NXT_NODE_GYP=node-gyp} + +$echo "configuring nodejs module" +$echo "configuring nodejs module..." >> $NXT_AUTOCONF_ERR + $echo -n "checking for node ..." $echo "checking for node ..." >> $NXT_AUTOCONF_ERR @@ -73,6 +74,7 @@ else exit 1; fi + $echo -n "checking for npm ..." $echo "checking for npm ..." >> $NXT_AUTOCONF_ERR @@ -90,6 +92,7 @@ else exit 1; fi + $echo -n "checking for node-gyp ..." $echo "checking for node-gyp ..." >> $NXT_AUTOCONF_ERR @@ -114,6 +117,7 @@ if grep ^$NXT_NODE: $NXT_MAKEFILE 2>&1 > /dev/null; then exit 1; fi + NXT_NODE_TMP=${NXT_BUILD_DIR}/src/${NXT_NODE}/unit-http NXT_NODE_TARBALL=${NXT_BUILD_DIR}/${NXT_NODE}-unit-http.tar.gz NXT_NODE_EXPORTS="export UNIT_SRC_PATH=${PWD}/src && \ @@ -125,8 +129,10 @@ cat << END >> $NXT_MAKEFILE .PHONY: ${NXT_NODE}-copy .PHONY: ${NXT_NODE}-install .PHONY: ${NXT_NODE}-uninstall +.PHONY: ${NXT_NODE}-local-install +.PHONY: ${NXT_NODE}-build +.PHONY: ${NXT_NODE}-publish -all: ${NXT_NODE}: ${NXT_NODE}-copy $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC ${NXT_NODE_EXPORTS} && \\ @@ -139,10 +145,14 @@ ${NXT_NODE}-copy: ${NXT_NODE_TARBALL}: ${NXT_NODE}-copy tar -zcvf ${NXT_NODE_TARBALL} -C ${NXT_NODE_TMP} . + ${NXT_NODE}-install: ${NXT_NODE_TARBALL} \ $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC ${NXT_NODE_EXPORTS} && \\ - ${NXT_NPM} install -g ${PWD}/${NXT_NODE_TARBALL} --unsafe-perm=true + ${NXT_NPM} install -g ${PWD}/${NXT_NODE_TARBALL} + +${NXT_NODE}-uninstall: + ${NXT_NPM} uninstall -g unit-http ${NXT_NODE}-local-install: ${NXT_NODE_TARBALL} \ $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC @@ -150,12 +160,10 @@ ${NXT_NODE}-local-install: ${NXT_NODE_TARBALL} \ mkdir -p \$(DESTDIR) && \\ cd \$(DESTDIR) && ${NXT_NPM} install ${PWD}/${NXT_NODE_TARBALL} + ${NXT_NODE}-build: ${NXT_NODE} ${NXT_NODE}-publish: ${NXT_NODE} cd ${NXT_NODE_TMP} && ${NXT_NPM} publish -${NXT_NODE}-uninstall: - ${NXT_NPM} uninstall -g unit-http - END -- cgit From ed8bfc669f0c6ac2b7cb367f6adcdf756b2f6cca Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Wed, 14 Nov 2018 20:12:47 +0300 Subject: Node.js: reworked installation procedure. Now by default "make install" installs the module globally. The "--local" configure option added for local installation. --- auto/modules/nodejs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/auto/modules/nodejs b/auto/modules/nodejs index 3138904a..443ee9d5 100644 --- a/auto/modules/nodejs +++ b/auto/modules/nodejs @@ -15,6 +15,7 @@ for nxt_option; do --node=*) NXT_NODE="$value" ;; --npm=*) NXT_NPM="$value" ;; --node-gyp=*) NXT_NODE_GYP="$value" ;; + --local=*) NXT_NODE_LOCAL="$value" ;; --help) cat << END @@ -22,6 +23,7 @@ for nxt_option; do --node=FILE set node executable --npm=FILE set npm executable --node-gyp=FILE set node-gyp executable + --local=DIRECTORY set directory path for local installation END exit 0 @@ -52,6 +54,7 @@ fi NXT_NODE=${NXT_NODE=node} NXT_NPM=${NXT_NPM=npm} NXT_NODE_GYP=${NXT_NODE_GYP=node-gyp} +NXT_NODE_LOCAL=${NXT_NODE_LOCAL=} $echo "configuring nodejs module" @@ -123,12 +126,19 @@ NXT_NODE_TARBALL=${NXT_BUILD_DIR}/${NXT_NODE}-unit-http.tar.gz NXT_NODE_EXPORTS="export UNIT_SRC_PATH=${PWD}/src && \ export UNIT_LIB_STATIC_PATH=${PWD}/${NXT_BUILD_DIR}/libunit.a" +if [ -n "$NXT_NODE_LOCAL" ]; then + NXT_NODE_INSTALL=local-install +else + NXT_NODE_INSTALL=install +fi + cat << END >> $NXT_MAKEFILE .PHONY: ${NXT_NODE} .PHONY: ${NXT_NODE}-copy .PHONY: ${NXT_NODE}-install .PHONY: ${NXT_NODE}-uninstall +.PHONY: ${NXT_NODE}-local-check .PHONY: ${NXT_NODE}-local-install .PHONY: ${NXT_NODE}-build .PHONY: ${NXT_NODE}-publish @@ -146,6 +156,8 @@ ${NXT_NODE_TARBALL}: ${NXT_NODE}-copy tar -zcvf ${NXT_NODE_TARBALL} -C ${NXT_NODE_TMP} . +install: ${NXT_NODE}-$NXT_NODE_INSTALL + ${NXT_NODE}-install: ${NXT_NODE_TARBALL} \ $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC ${NXT_NODE_EXPORTS} && \\ @@ -154,11 +166,21 @@ ${NXT_NODE}-install: ${NXT_NODE_TARBALL} \ ${NXT_NODE}-uninstall: ${NXT_NPM} uninstall -g unit-http -${NXT_NODE}-local-install: ${NXT_NODE_TARBALL} \ +${NXT_NODE}-local-check: + @test -n "\$(DESTDIR)$NXT_NODE_LOCAL" \\ + || (echo; \\ + echo "error: to make ${NXT_NODE}-local-install you need either"; \\ + echo " to configure --local option"; \\ + echo " or to set DESTDIR environment variable."; \\ + echo; \\ + exit 1) + +${NXT_NODE}-local-install: ${NXT_NODE_TARBALL} ${NXT_NODE}-local-check \ $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC ${NXT_NODE_EXPORTS} && \\ - mkdir -p \$(DESTDIR) && \\ - cd \$(DESTDIR) && ${NXT_NPM} install ${PWD}/${NXT_NODE_TARBALL} + mkdir -p \$(DESTDIR)${NXT_NODE_LOCAL} && \\ + cd \$(DESTDIR)${NXT_NODE_LOCAL} && \\ + ${NXT_NPM} install ${PWD}/${NXT_NODE_TARBALL} ${NXT_NODE}-build: ${NXT_NODE} -- cgit From 08e0082e070354919de9584a8d26436a1dadeac0 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Thu, 15 Nov 2018 11:59:03 +0300 Subject: Fixed discovering of modules on 64-bit big-endian systems. The nxt_conf_map_object() function used nxt_int_t for NXT_CONF_MAP_INT, which was 8 bytes long on 64-bit systems. But the nxt_port_main_start_worker_handler() used it to map into the int field of the nxt_common_app_conf_t structure, which was 4 bytes. As the result, on a 64-bit big-endian system all the meaningful module type numbers were assigned into the gap above the "type" field. The bug was discovered on IBM/S390x. --- src/nxt_conf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nxt_conf.c b/src/nxt_conf.c index 1aeafc06..2255e12f 100644 --- a/src/nxt_conf.c +++ b/src/nxt_conf.c @@ -525,7 +525,7 @@ nxt_conf_map_object(nxt_mp_t *mp, nxt_conf_value_t *value, nxt_conf_map_t *map, uint8_t ui8; int32_t i32; int64_t i64; - nxt_int_t i; + int i; ssize_t size; off_t off; nxt_msec_t msec; -- cgit From b033fb329fc14e6469596821508c487e3ed6ff82 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Thu, 15 Nov 2018 13:00:58 +0300 Subject: Fixed lvlhsh test on 64-bit big-endian systems. The nxt_murmur_hash2() generated 4-byte hash that was stored in uintptr_t, which was 8 bytes long on 64-bit systems. At each iteration, it took the previous key and hashed it again. The problem was that it took only the first 4 bytes of the key, and these 4 bytes were always zero on 64-bit big-endian system. That resulted in equal keys at each iteration. The bug was discovered on IBM/S390x. --- src/test/nxt_lvlhsh_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/nxt_lvlhsh_test.c b/src/test/nxt_lvlhsh_test.c index 3dc56076..2e1e0b20 100644 --- a/src/test/nxt_lvlhsh_test.c +++ b/src/test/nxt_lvlhsh_test.c @@ -131,7 +131,7 @@ nxt_int_t nxt_lvlhsh_test(nxt_thread_t *thr, nxt_uint_t n, nxt_bool_t use_pool) { void *value; - uintptr_t key; + uint32_t key; nxt_mp_t *mp; nxt_nsec_t start, end; nxt_uint_t i; -- cgit From 71f4cb91340b656397eaaa356755b4a1e31c8010 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Thu, 15 Nov 2018 15:24:45 +0300 Subject: Node.js: added reference count increment for the Unit object. We increase the number to the Unit object so that it lives forever. This is necessary so that the garbage collector does not delete the Unit object. --- src/nodejs/unit-http/http_server.js | 2 ++ src/nodejs/unit-http/unit.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/nodejs/unit-http/http_server.js b/src/nodejs/unit-http/http_server.js index ddacb420..b35ad259 100755 --- a/src/nodejs/unit-http/http_server.js +++ b/src/nodejs/unit-http/http_server.js @@ -333,6 +333,8 @@ Server.prototype.run_events = function (server, req, res) { }); Promise.resolve().then(() => { + req.emit("finish"); + if (res.finished) { unit_lib.unit_response_end(res); } diff --git a/src/nodejs/unit-http/unit.cpp b/src/nodejs/unit-http/unit.cpp index 97238834..bc6fc7db 100644 --- a/src/nodejs/unit-http/unit.cpp +++ b/src/nodejs/unit-http/unit.cpp @@ -111,6 +111,7 @@ napi_value Unit::create(napi_env env, napi_callback_info info) { Unit *obj; + napi_ref ref; napi_value target, cons, instance, jsthis; napi_status status; @@ -135,6 +136,11 @@ Unit::create(napi_env env, napi_callback_info info) goto failed; } + status = napi_create_reference(env, jsthis, 1, &ref); + if (status != napi_ok) { + goto failed; + } + return jsthis; } @@ -149,6 +155,11 @@ Unit::create(napi_env env, napi_callback_info info) goto failed; } + status = napi_create_reference(env, instance, 1, &ref); + if (status != napi_ok) { + goto failed; + } + return instance; failed: -- cgit From 06b404feb17dec9e3a84da31e213f21a0a9b4846 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Thu, 15 Nov 2018 15:39:34 +0300 Subject: Node.js: added correct exit processing. Node.js processes didn't exit after the changes in b9f7635e6be2, as the quit command from port wasn't handled by the module. --- src/nodejs/unit-http/unit.cpp | 60 ++++++++++++++++++++++++++++++------------- src/nodejs/unit-http/unit.h | 1 + 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/nodejs/unit-http/unit.cpp b/src/nodejs/unit-http/unit.cpp index bc6fc7db..788a5cc8 100644 --- a/src/nodejs/unit-http/unit.cpp +++ b/src/nodejs/unit-http/unit.cpp @@ -14,6 +14,12 @@ napi_ref Unit::constructor_; +struct nxt_nodejs_ctx_t { + nxt_unit_port_id_t port_id; + uv_poll_t poll; +}; + + Unit::Unit(napi_env env): env_(env), wrapper_(nullptr), @@ -197,6 +203,7 @@ Unit::create_server(napi_env env, napi_callback_info info) unit_init.callbacks.request_handler = request_handler; unit_init.callbacks.add_port = add_port; unit_init.callbacks.remove_port = remove_port; + unit_init.callbacks.quit = quit; obj->unit_ctx_ = nxt_unit_init(&unit_init); if (obj->unit_ctx_ == NULL) { @@ -355,11 +362,11 @@ nxt_uv_read_callback(uv_poll_t *handle, int status, int events) int Unit::add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) { - int err; - Unit *obj; - uv_loop_t *loop; - uv_poll_t *uv_handle; - napi_status status; + int err; + Unit *obj; + uv_loop_t *loop; + napi_status status; + nxt_nodejs_ctx_t *node_ctx; if (port->in_fd != -1) { obj = reinterpret_cast(ctx->unit->data); @@ -376,48 +383,65 @@ Unit::add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) return NXT_UNIT_ERROR; } - uv_handle = new uv_poll_t; + node_ctx = new nxt_nodejs_ctx_t; - err = uv_poll_init(loop, uv_handle, port->in_fd); + err = uv_poll_init(loop, &node_ctx->poll, port->in_fd); if (err < 0) { napi_throw_error(obj->env_, NULL, "Failed to init uv.poll"); return NXT_UNIT_ERROR; } - err = uv_poll_start(uv_handle, UV_READABLE, nxt_uv_read_callback); + err = uv_poll_start(&node_ctx->poll, UV_READABLE, nxt_uv_read_callback); if (err < 0) { napi_throw_error(obj->env_, NULL, "Failed to start uv.poll"); return NXT_UNIT_ERROR; } - port->data = uv_handle; - uv_handle->data = ctx; + ctx->data = node_ctx; + + node_ctx->port_id = port->id; + node_ctx->poll.data = ctx; } return nxt_unit_add_port(ctx, port); } +inline bool +operator == (const nxt_unit_port_id_t &p1, const nxt_unit_port_id_t &p2) +{ + return p1.pid == p2.pid && p1.id == p2.id; +} + + void Unit::remove_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id) { - nxt_unit_port_t *port; + nxt_nodejs_ctx_t *node_ctx; - port = nxt_unit_find_port(ctx, port_id); - if (port == NULL) { - return; - } + if (ctx->data != NULL) { + node_ctx = (nxt_nodejs_ctx_t *) ctx->data; + + if (node_ctx->port_id == *port_id) { + uv_poll_stop(&node_ctx->poll); - if (port->in_fd != -1 && port->data != NULL) { - uv_poll_stop((uv_poll_t *) port->data); + delete node_ctx; - delete (uv_poll_t *) port->data; + ctx->data = NULL; + } } nxt_unit_remove_port(ctx, port_id); } +void +Unit::quit(nxt_unit_ctx_t *ctx) +{ + nxt_unit_done(ctx); +} + + napi_value Unit::get_server_object() { diff --git a/src/nodejs/unit-http/unit.h b/src/nodejs/unit-http/unit.h index 90c67efc..5f541cc4 100644 --- a/src/nodejs/unit-http/unit.h +++ b/src/nodejs/unit-http/unit.h @@ -40,6 +40,7 @@ private: static void request_handler(nxt_unit_request_info_t *req); static int add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port); static void remove_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id); + static void quit(nxt_unit_ctx_t *ctx); napi_value get_server_object(); -- cgit From fb18a09cd748ff0107d4e27e514c9f5caf3aa5e6 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Thu, 15 Nov 2018 15:21:52 +0300 Subject: Node.js: fixed handling of response header fields. This fixes two issues: - values for mutiple header fields with the same name passed as arrays were converted to string; - the type of field value wasn't preserved as required by specification. --- src/nodejs/unit-http/http_server.js | 2 +- src/nodejs/unit-http/unit.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/nodejs/unit-http/http_server.js b/src/nodejs/unit-http/http_server.js index b35ad259..331778a3 100755 --- a/src/nodejs/unit-http/http_server.js +++ b/src/nodejs/unit-http/http_server.js @@ -78,7 +78,7 @@ ServerResponse.prototype.setHeader = function setHeader(key, value) { this.removeHeader(key); - this.headers[key] = value + ""; + this.headers[key] = value; this.headers_len += header_len + (header_key_len * header_count); this.headers_count += header_count; }; diff --git a/src/nodejs/unit-http/unit.cpp b/src/nodejs/unit-http/unit.cpp index 788a5cc8..be64a59b 100644 --- a/src/nodejs/unit-http/unit.cpp +++ b/src/nodejs/unit-http/unit.cpp @@ -696,6 +696,7 @@ Unit::response_send_headers(napi_env env, napi_callback_info info) napi_value this_arg, headers, keys, name, value, array_val; napi_value req_num; napi_status status; + napi_valuetype val_type; nxt_unit_field_t *f; nxt_unit_request_info_t *req; napi_value argv[5]; @@ -805,6 +806,18 @@ Unit::response_send_headers(napi_env env, napi_callback_info info) goto failed; } + napi_typeof(env, array_val, &val_type); + if (status != napi_ok) { + goto failed; + } + + if (val_type != napi_string) { + status = napi_coerce_to_string(env, array_val, &array_val); + if (status != napi_ok) { + goto failed; + } + } + status = napi_get_value_string_latin1(env, array_val, ptr, header_len, &value_len); @@ -830,6 +843,18 @@ Unit::response_send_headers(napi_env env, napi_callback_info info) } } else { + napi_typeof(env, value, &val_type); + if (status != napi_ok) { + goto failed; + } + + if (val_type != napi_string) { + status = napi_coerce_to_string(env, value, &value); + if (status != napi_ok) { + goto failed; + } + } + status = napi_get_value_string_latin1(env, value, ptr, header_len, &value_len); if (status != napi_ok) { -- cgit From 5c2021f8340566cbdac9dcc8e32c710d4b763a43 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Thu, 15 Nov 2018 14:42:51 +0300 Subject: Node.js: res.write() must return a bool value. --- src/nodejs/unit-http/http_server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nodejs/unit-http/http_server.js b/src/nodejs/unit-http/http_server.js index 331778a3..57163c0b 100755 --- a/src/nodejs/unit-http/http_server.js +++ b/src/nodejs/unit-http/http_server.js @@ -227,7 +227,7 @@ ServerResponse.prototype._writeBody = function(chunk, encoding, callback) { ServerResponse.prototype.write = function write(chunk, encoding, callback) { this._writeBody(chunk, encoding, callback); - return this; + return true; }; ServerResponse.prototype.end = function end(chunk, encoding, callback) { -- cgit From 2b4d83cbd8a228b0004e3831c9d933400dede3c1 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Thu, 15 Nov 2018 15:53:35 +0300 Subject: Node.js: npm package readme cleanup. --- src/nodejs/unit-http/README.md | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/src/nodejs/unit-http/README.md b/src/nodejs/unit-http/README.md index 71a4067a..b6b975e4 100644 --- a/src/nodejs/unit-http/README.md +++ b/src/nodejs/unit-http/README.md @@ -1,21 +1,5 @@ +[](https://unit.nginx.org) + # Node.js Package for NGINX Unit -[](https://unit.nginx.org) -Node.js support package for NGINX Unit. For details, see [NGINX Unit documentation](https://unit.nginx.org). - -## Installation - -```bash -npm i unit-http -``` - -## Usage - -```javascript -var http = require('unit-http'); -``` - -## License - -Apache 2.0 -- cgit From b4e2ec43d1f5bc904800c76e1d02b96d7683765f Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Thu, 15 Nov 2018 15:56:09 +0300 Subject: Added version 1.6 CHANGES. --- CHANGES | 22 ++++++++++++++++++ docs/changes.xml | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/CHANGES b/CHANGES index b1047284..69761f50 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,26 @@ +Changes with Unit 1.6 15 Nov 2018 + + *) Change: "make install" now installs Node.js module as well if it was + configured. + + *) Feature: "--local" ./configure option to install Node.js module + locally. + + *) Bugfix: Node.js module might have crashed due to broken reference + counting. + + *) Bugfix: asynchronous operations in Node.js might not have worked. + + *) Bugfix: various compatibility issues with Node.js applications. + + *) Bugfix: "freed pointer is out of pool" alerts might have appeared in + log. + + *) Bugfix: module discovery didn't work on 64-bit big-endian systems + like IBM/S390x. + + Changes with Unit 1.5 25 Oct 2018 *) Change: the "type" of application object for Go was changed to diff --git a/docs/changes.xml b/docs/changes.xml index 5be0a94e..b3bc33ee 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -5,6 +5,74 @@ + + + + +NGINX Unit updated to 1.6. + + + + + + + + + + +"make install" now installs Node.js module as well if it was configured. + + + + + +"--local" ./configure option to install Node.js module locally. + + + + + +Node.js module might have crashed due to broken reference counting. + + + + + +asynchronous operations in Node.js might not have worked. + + + + + +various compatibility issues with Node.js applications. + + + + + +"freed pointer is out of pool" alerts might have appeared in log. + + + + + +module discovery didn't work on 64-bit big-endian systems like IBM/S390x. + + + + + + " -ENV UNIT_VERSION 1.5-1~stretch +ENV UNIT_VERSION 1.6-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.go1.7-dev b/pkg/docker/Dockerfile.go1.7-dev index c39d8f04..2c6975e2 100644 --- a/pkg/docker/Dockerfile.go1.7-dev +++ b/pkg/docker/Dockerfile.go1.7-dev @@ -2,7 +2,7 @@ FROM debian:stretch-slim LABEL maintainer="NGINX Docker Maintainers " -ENV UNIT_VERSION 1.5-1~stretch +ENV UNIT_VERSION 1.6-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.go1.8-dev b/pkg/docker/Dockerfile.go1.8-dev index 0db00501..1cd1acfc 100644 --- a/pkg/docker/Dockerfile.go1.8-dev +++ b/pkg/docker/Dockerfile.go1.8-dev @@ -2,7 +2,7 @@ FROM debian:stretch-slim LABEL maintainer="NGINX Docker Maintainers " -ENV UNIT_VERSION 1.5-1~stretch +ENV UNIT_VERSION 1.6-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.minimal b/pkg/docker/Dockerfile.minimal index b6735b15..0ffff5c9 100644 --- a/pkg/docker/Dockerfile.minimal +++ b/pkg/docker/Dockerfile.minimal @@ -2,7 +2,7 @@ FROM debian:stretch-slim LABEL maintainer="NGINX Docker Maintainers " -ENV UNIT_VERSION 1.5-1~stretch +ENV UNIT_VERSION 1.6-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.perl5.24 b/pkg/docker/Dockerfile.perl5.24 index bb27e721..9cbbc645 100644 --- a/pkg/docker/Dockerfile.perl5.24 +++ b/pkg/docker/Dockerfile.perl5.24 @@ -2,7 +2,7 @@ FROM debian:stretch-slim LABEL maintainer="NGINX Docker Maintainers " -ENV UNIT_VERSION 1.5-1~stretch +ENV UNIT_VERSION 1.6-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.php7.0 b/pkg/docker/Dockerfile.php7.0 index fef46c83..70ea8bbc 100644 --- a/pkg/docker/Dockerfile.php7.0 +++ b/pkg/docker/Dockerfile.php7.0 @@ -2,7 +2,7 @@ FROM debian:stretch-slim LABEL maintainer="NGINX Docker Maintainers " -ENV UNIT_VERSION 1.5-1~stretch +ENV UNIT_VERSION 1.6-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.python2.7 b/pkg/docker/Dockerfile.python2.7 index d02ef003..4cb4d5f3 100644 --- a/pkg/docker/Dockerfile.python2.7 +++ b/pkg/docker/Dockerfile.python2.7 @@ -2,7 +2,7 @@ FROM debian:stretch-slim LABEL maintainer="NGINX Docker Maintainers " -ENV UNIT_VERSION 1.5-1~stretch +ENV UNIT_VERSION 1.6-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.python3.5 b/pkg/docker/Dockerfile.python3.5 index 67c7e3d6..26c54174 100644 --- a/pkg/docker/Dockerfile.python3.5 +++ b/pkg/docker/Dockerfile.python3.5 @@ -2,7 +2,7 @@ FROM debian:stretch-slim LABEL maintainer="NGINX Docker Maintainers " -ENV UNIT_VERSION 1.5-1~stretch +ENV UNIT_VERSION 1.6-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.ruby2.3 b/pkg/docker/Dockerfile.ruby2.3 index 93792864..b0d9de49 100644 --- a/pkg/docker/Dockerfile.ruby2.3 +++ b/pkg/docker/Dockerfile.ruby2.3 @@ -2,7 +2,7 @@ FROM debian:stretch-slim LABEL maintainer="NGINX Docker Maintainers " -ENV UNIT_VERSION 1.5-1~stretch +ENV UNIT_VERSION 1.6-1~stretch RUN set -x \ && apt-get update \ -- cgit From a4b02e17382ccbfc19410c644004c4615b2c2c29 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Thu, 15 Nov 2018 16:06:42 +0300 Subject: Added tag 1.6 for changeset d411e7fdee9e --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index c755a46f..06061b5b 100644 --- a/.hgtags +++ b/.hgtags @@ -11,3 +11,4 @@ fbe7f5a3867e9559ef0884786fe5150aa60414e6 1.2 b3cf22b8a17e0e35ca80decb03ed2cceb662c3de 1.3 8f4524a9cf87fbddf626302da071f5055cf33f28 1.4 b3dee0cc5a4edd046345511769b5cfec49044f1c 1.5 +d411e7fdee9e03036adb652f8d9f4c45a420bdd5 1.6 -- cgit