From 425d56037247480eb9c3f839fb79a88f2aa2f36b Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Fri, 28 Sep 2018 15:05:35 +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 1bbd9ee5..670010f8 100644 --- a/src/nxt_main.h +++ b/src/nxt_main.h @@ -11,8 +11,8 @@ #include -#define NXT_VERSION "1.4" -#define NXT_VERNUM 10400 +#define NXT_VERSION "1.5" +#define NXT_VERNUM 10500 #define NXT_SERVER "Unit/" NXT_VERSION -- cgit From 92da8dae1e4194698ace12e6a51df5d9431e00c4 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Fri, 28 Sep 2018 15:12:47 +0300 Subject: Fixed bug in socket write error handling. The bug has been introduced in e3972a4a9c73. --- src/nxt_conn_write.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/nxt_conn_write.c b/src/nxt_conn_write.c index 73c3fa02..80d6f5cf 100644 --- a/src/nxt_conn_write.c +++ b/src/nxt_conn_write.c @@ -127,7 +127,9 @@ nxt_conn_io_write(nxt_task_t *task, void *obj, void *data) return; } - /* ret == NXT_ERROR */ + if (ret != NXT_ERROR) { + return; + } nxt_fd_event_block_write(engine, &c->socket); -- cgit From b5d4fc939edca5ea5858b66d5fcf789b660df243 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Fri, 28 Sep 2018 17:32:02 +0300 Subject: Disabled chunked transfer encoding for 204 responses. --- src/nxt_h1proto.c | 3 ++- src/nxt_http.h | 1 + test/test_python_application.py | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index 3e5044b7..70d6e5d8 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -967,7 +967,8 @@ nxt_h1p_request_header_send(nxt_task_t *task, nxt_http_request_t *r) http11 = (h1p->parser.version.s.minor != '0'); if (r->resp.content_length == NULL || r->resp.content_length->skip) { - if (http11) { + + if (http11 && n != NXT_HTTP_NO_CONTENT) { h1p->chunked = 1; size += nxt_length(chunked); /* Trailing CRLF will be added by the first chunk header. */ diff --git a/src/nxt_http.h b/src/nxt_http.h index 1c7ed8bb..b2111f90 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -12,6 +12,7 @@ typedef enum { NXT_HTTP_INVALID = 0, NXT_HTTP_OK = 200, + NXT_HTTP_NO_CONTENT = 204, NXT_HTTP_MULTIPLE_CHOICES = 300, NXT_HTTP_MOVED_PERMANENTLY = 301, diff --git a/test/test_python_application.py b/test/test_python_application.py index f1e2cbf7..e71b6432 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -60,7 +60,6 @@ class TestUnitPythonApplication(unit.TestUnitApplicationPython): self.assertEqual(self.get()['headers']['Server-Port'], '7080', 'Server-Port header') - @unittest.expectedFailure def test_python_application_204_transfer_encoding(self): self.load('204_no_content') -- cgit From 02a4dd7c783a43110a4422b3b76ccf8184fa870b Mon Sep 17 00:00:00 2001 From: Andrei Belov Date: Mon, 1 Oct 2018 09:41:03 +0300 Subject: Skipping minor entries while producing generic CHANGES. Currently we consider any changes with revision other than 1 as packages-specific, thus there is no need to include such entries to the generic Unit change log. --- docs/changes.xsls | 5 +++++ docs/changes.xslt | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/docs/changes.xsls b/docs/changes.xsls index f2ba1c8e..2f3bcc46 100644 --- a/docs/changes.xsls +++ b/docs/changes.xsls @@ -63,6 +63,9 @@ X:template = "changes" { X:var apply = { !string_in_list(list="@apply", string="$pkgname") } X:var pkgname_ = { !beautify(pkgname="$pkgname") } + X:choose { + X:when "$pkgname='unit' and $format='generic' and @rev!=1" {} + X:otherwise { X:if "$apply=$pkgname" { X:if "$format='generic'" { @@ -112,6 +115,8 @@ X:template = "changes" { X:text { } } } + } + } } diff --git a/docs/changes.xslt b/docs/changes.xslt index 22abb656..032d5c37 100644 --- a/docs/changes.xslt +++ b/docs/changes.xslt @@ -64,6 +64,9 @@ + + + @@ -113,6 +116,8 @@ + + -- cgit From db1e01d9924855fa52aab47fcb0e74b22a876eb1 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Mon, 1 Oct 2018 15:06:31 +0300 Subject: Mention of --openssl configure option in help. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This closes #171 issue on GitHub. Thanks to 洪志道 (Hong Zhi Dao). --- auto/help | 2 ++ 1 file changed, 2 insertions(+) diff --git a/auto/help b/auto/help index 98c877fb..4d0b84e9 100644 --- a/auto/help +++ b/auto/help @@ -33,6 +33,8 @@ cat << END --no-ipv6 disable IPv6 support --no-unix-sockets disable Unix domain sockets support + --openssl enable OpenSSL library usage + --debug enable debug logging -- cgit From e51ab1b2cbb10ef5a48d67ce7f492ddca481a5b7 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Mon, 1 Oct 2018 15:06:31 +0300 Subject: Fixed error log time caching resolution. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to 洪志道 (Hong Zhi Dao). --- src/nxt_app_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nxt_app_log.c b/src/nxt_app_log.c index 83eac371..0ecd9aac 100644 --- a/src/nxt_app_log.c +++ b/src/nxt_app_log.c @@ -97,7 +97,7 @@ static nxt_time_string_t nxt_log_error_time_cache = { "%4d/%02d/%02d %02d:%02d:%02d ", nxt_length("1970/09/28 12:00:00 "), NXT_THREAD_TIME_LOCAL, - NXT_THREAD_TIME_MSEC, + NXT_THREAD_TIME_SEC, }; -- cgit From 3c2eddb183684e577bca967543a52067edbda9a5 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Mon, 1 Oct 2018 15:06:31 +0300 Subject: Allowing keep-alive connections after 204 responses. This was unintentionally disabled by 7b5026a0bdeb. --- src/nxt_h1proto.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index 70d6e5d8..ed159c93 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -968,11 +968,13 @@ nxt_h1p_request_header_send(nxt_task_t *task, nxt_http_request_t *r) if (r->resp.content_length == NULL || r->resp.content_length->skip) { - if (http11 && n != NXT_HTTP_NO_CONTENT) { - h1p->chunked = 1; - size += nxt_length(chunked); - /* Trailing CRLF will be added by the first chunk header. */ - size -= nxt_length("\r\n"); + if (http11) { + if (n != NXT_HTTP_NO_CONTENT) { + h1p->chunked = 1; + size += nxt_length(chunked); + /* Trailing CRLF will be added by the first chunk header. */ + size -= nxt_length("\r\n"); + } } else { h1p->keepalive = 0; -- cgit From d54d806c52756ab65d61713589029627ffa72c5d Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Mon, 1 Oct 2018 15:06:31 +0300 Subject: Disabled chunked transfer encoding for 304 responses as well. According to RFC 7232: | A 304 response cannot contain a message-body; it is always terminated | by the first empty line after the header fields. --- src/nxt_h1proto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index ed159c93..2194e56f 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -969,7 +969,7 @@ nxt_h1p_request_header_send(nxt_task_t *task, nxt_http_request_t *r) if (r->resp.content_length == NULL || r->resp.content_length->skip) { if (http11) { - if (n != NXT_HTTP_NO_CONTENT) { + if (n != NXT_HTTP_NOT_MODIFIED && n != NXT_HTTP_NO_CONTENT) { h1p->chunked = 1; size += nxt_length(chunked); /* Trailing CRLF will be added by the first chunk header. */ -- cgit From cb1b0744930801b6e06d05f788c3e7cb40163167 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Tue, 2 Oct 2018 19:46:06 +0300 Subject: Making port fd blocking on app side and non-blocking in Unit. This issue was introduced in libunit commit (e0f0cd7d244a). All port sockets in application should be in blocking mode whereas Unit itself operates non-blocking sockets. Having non-blocking sockets in application may cause send error during intensive response packets generation. See https://mailman.nginx.org/pipermail/unit/2018-October/000080.html. --- src/nxt_port.c | 2 ++ src/nxt_unit.c | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/nxt_port.c b/src/nxt_port.c index 3d18fa67..30719ad3 100644 --- a/src/nxt_port.c +++ b/src/nxt_port.c @@ -276,6 +276,8 @@ nxt_port_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) nxt_process_use(task, process, -1); + nxt_fd_nonblocking(task, msg->fd); + port->pair[0] = -1; port->pair[1] = msg->fd; port->max_size = new_port_msg->max_size; diff --git a/src/nxt_unit.c b/src/nxt_unit.c index 0f46dc7e..251c5219 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -510,7 +510,7 @@ int nxt_unit_process_msg(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id, void *buf, size_t buf_size, void *oob, size_t oob_size) { - int fd, rc; + int fd, rc, nb; pid_t pid; nxt_queue_t incoming_buf; struct cmsghdr *cm; @@ -611,6 +611,15 @@ nxt_unit_process_msg(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id, port_msg->stream, (int) new_port_msg->pid, (int) new_port_msg->id, fd); + nb = 0; + + if (nxt_slow_path(ioctl(fd, FIONBIO, &nb) == -1)) { + nxt_unit_alert(ctx, "#%"PRIu32": new_port: ioctl(%d, FIONBIO, 0) " + "failed: %s (%d)", fd, strerror(errno), errno); + + goto fail; + } + nxt_unit_port_id_init(&new_port.id, new_port_msg->pid, new_port_msg->id); -- cgit From c8b30ef4da02278308e0ed050d9a937134a6aa45 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Tue, 2 Oct 2018 19:49:48 +0300 Subject: Go: fixing typo in log messages. --- src/go/unit/nxt_cgo_lib.c | 2 +- src/go/unit/port.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/go/unit/nxt_cgo_lib.c b/src/go/unit/nxt_cgo_lib.c index 9c080730..172bef88 100644 --- a/src/go/unit/nxt_cgo_lib.c +++ b/src/go/unit/nxt_cgo_lib.c @@ -203,5 +203,5 @@ nxt_cgo_request_done(uintptr_t req, int res) void nxt_cgo_warn(uintptr_t msg, uint32_t msg_len) { - nxt_unit_warn(NULL, ".*s", (int) msg_len, (char *) msg); + nxt_unit_warn(NULL, "%.*s", (int) msg_len, (char *) msg); } diff --git a/src/go/unit/port.go b/src/go/unit/port.go index f716c9ec..a68cae74 100644 --- a/src/go/unit/port.go +++ b/src/go/unit/port.go @@ -163,7 +163,7 @@ func nxt_go_port_recv(pid C.int, id C.int, buf unsafe.Pointer, buf_size C.int, GoBytes(oob, oob_size)) if err != nil { - nxt_go_warn("write result %d (%d), %s", n, oobn, err) + nxt_go_warn("read result %d (%d), %s", n, oobn, err) } return C.ssize_t(n) -- cgit From 141ee2aa326d54eeecc2ef96f61e2d2d8068b6b1 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Tue, 2 Oct 2018 19:49:49 +0300 Subject: Filling cmsghdr with 0 to pass Go 1.11 message validation. --- src/nxt_unit.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/nxt_unit.c b/src/nxt_unit.c index 251c5219..0d1be557 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -2167,9 +2167,12 @@ nxt_unit_send_mmap(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id, int fd) msg.mf = 0; msg.tracking = 0; -#if (NXT_VALGRIND) + /* + * Fill all padding fields with 0. + * Code in Go 1.11 validate cmsghdr using padding field as part of len. + * See Cmsghdr definition and socketControlMessageHeaderAndData function. + */ memset(&cmsg, 0, sizeof(cmsg)); -#endif cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int)); cmsg.cm.cmsg_level = SOL_SOCKET; @@ -3001,9 +3004,7 @@ nxt_unit_send_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *dst, m.new_port.max_size = 16 * 1024; m.new_port.max_share = 64 * 1024; -#if (NXT_VALGRIND) memset(&cmsg, 0, sizeof(cmsg)); -#endif cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int)); cmsg.cm.cmsg_level = SOL_SOCKET; -- cgit From ea62327b008b39dc48a51aa80343b20a0a122cd6 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Wed, 3 Oct 2018 17:50:03 +0300 Subject: Added Node.js support. --- auto/modules/conf | 4 + auto/modules/nodejs | 161 +++++++ auto/save | 2 + src/nodejs/unit-http/README.md | 2 + src/nodejs/unit-http/addon.cpp | 15 + src/nodejs/unit-http/binding.gyp | 12 + src/nodejs/unit-http/binding_pub.gyp | 7 + src/nodejs/unit-http/http.js | 23 + src/nodejs/unit-http/http_server.js | 331 +++++++++++++ src/nodejs/unit-http/package.json | 29 ++ src/nodejs/unit-http/socket.js | 99 ++++ src/nodejs/unit-http/unit.cpp | 905 +++++++++++++++++++++++++++++++++++ src/nodejs/unit-http/unit.h | 77 +++ 13 files changed, 1667 insertions(+) create mode 100644 auto/modules/nodejs create mode 100644 src/nodejs/unit-http/README.md create mode 100644 src/nodejs/unit-http/addon.cpp create mode 100644 src/nodejs/unit-http/binding.gyp create mode 100644 src/nodejs/unit-http/binding_pub.gyp create mode 100755 src/nodejs/unit-http/http.js create mode 100755 src/nodejs/unit-http/http_server.js create mode 100644 src/nodejs/unit-http/package.json create mode 100755 src/nodejs/unit-http/socket.js create mode 100644 src/nodejs/unit-http/unit.cpp create mode 100644 src/nodejs/unit-http/unit.h diff --git a/auto/modules/conf b/auto/modules/conf index 93d28601..409b4bea 100644 --- a/auto/modules/conf +++ b/auto/modules/conf @@ -25,6 +25,10 @@ case "$nxt_module" in . auto/modules/ruby ;; + nodejs) + . auto/modules/nodejs + ;; + *) echo echo $0: error: invalid module \"$nxt_module\". diff --git a/auto/modules/nodejs b/auto/modules/nodejs new file mode 100644 index 00000000..25e75f01 --- /dev/null +++ b/auto/modules/nodejs @@ -0,0 +1,161 @@ + +# Copyright (C) NGINX, Inc. + + +shift + +for nxt_option; do + + case "$nxt_option" in + -*=*) value=`echo "$nxt_option" | sed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) value="" ;; + esac + + case "$nxt_option" in + --node=*) NXT_NODE="$value" ;; + --npm=*) NXT_NPM="$value" ;; + --node-gyp=*) NXT_NODE_GYP="$value" ;; + + --help) + cat << END + + --node=NAME set node executable + --npm=NAME set npm executable + --node-gyp=NAME set node-gyp executable + +END + exit 0 + ;; + + *) + echo + echo $0: error: invalid Node option \"$nxt_option\" + echo + exit 1 + ;; + + esac + +done + + +if [ ! -f $NXT_AUTOCONF_DATA ]; then + echo + echo Please run common $0 before configuring module \"$nxt_module\". + echo + exit 1 +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 -n "checking for node ..." +$echo "checking for node ..." >> $NXT_AUTOCONF_ERR + +if /bin/sh -c "${NXT_NODE} -v" >> $NXT_AUTOCONF_ERR 2>&1; then + $echo " found" + + NXT_NODE_VERSION="`${NXT_NODE} -v`" + $echo " + node version ${NXT_NODE_VERSION}" + +else + $echo " not found" + $echo + $echo $0: error: no Node found. + $echo + exit 1; +fi + +$echo -n "checking for npm ..." +$echo "checking for npm ..." >> $NXT_AUTOCONF_ERR + +if /bin/sh -c "${NXT_NPM} -v" >> $NXT_AUTOCONF_ERR 2>&1; then + $echo " found" + + NXT_NPM_VERSION="`${NXT_NPM} -v`" + $echo " + npm version ${NXT_NPM_VERSION}" + +else + $echo " not found" + $echo + $echo $0: error: no npm found. + $echo + exit 1; +fi + +$echo -n "checking for node-gyp ..." +$echo "checking for node-gyp ..." >> $NXT_AUTOCONF_ERR + +if /bin/sh -c "${NXT_NODE_GYP} -v" >> $NXT_AUTOCONF_ERR 2>&1; then + $echo " found" + + NXT_NODE_GYP_VERSION="`${NXT_NODE_GYP} -v`" + $echo " + node-gyp version ${NXT_NODE_GYP_VERSION}" + +else + $echo " not found" + $echo + $echo $0: error: no node-gyp found. + $echo + exit 1; +fi + +if grep ^$NXT_NODE: $NXT_MAKEFILE 2>&1 > /dev/null; then + $echo + $echo $0: error: duplicate \"$NXT_NODE\" package configured. + $echo + exit 1; +fi + +NXT_NODE_TMP=${NXT_BUILD_DIR}/src/${NXT_NODE}/unit-http +NXT_NODE_TARBALL=${PWD}/${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" + +cat << END >> $NXT_MAKEFILE + +.PHONY: ${NXT_NODE} +.PHONY: ${NXT_NODE}-copy +.PHONY: ${NXT_NODE}-install +.PHONY: ${NXT_NODE}-uninstall + +all: + +${NXT_NODE}: ${NXT_NODE}-copy $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC + ${NXT_NODE_EXPORTS} && \\ + cd ${NXT_NODE_TMP} && ${NXT_NODE_GYP} configure build clean + +${NXT_NODE}-copy: + mkdir -p ${NXT_BUILD_DIR}/src/ + cp -rp src/nodejs/ ${NXT_BUILD_DIR}/src/${NXT_NODE} + +${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 ${NXT_NODE_TARBALL} --unsafe-perm=true + +${NXT_NODE}-local-install: ${NXT_NODE_TARBALL} \ + $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC + ${NXT_NODE_EXPORTS} && \\ + mkdir -p \$(DESTDIR) && \\ + cd \$(DESTDIR) && ${NXT_NPM} install ${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 diff --git a/auto/save b/auto/save index 3a04a698..350c9c1f 100644 --- a/auto/save +++ b/auto/save @@ -26,6 +26,8 @@ echo=$NXT_BUILD_DIR/echo NXT_LIB_AUX_CFLAGS= NXT_LIB_AUX_LIBS= +NXT_LIB_UNIT_STATIC='$NXT_LIB_UNIT_STATIC' + NXT_MODULES='$NXT_MODULES' END diff --git a/src/nodejs/unit-http/README.md b/src/nodejs/unit-http/README.md new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/src/nodejs/unit-http/README.md @@ -0,0 +1,2 @@ + + diff --git a/src/nodejs/unit-http/addon.cpp b/src/nodejs/unit-http/addon.cpp new file mode 100644 index 00000000..6ced9538 --- /dev/null +++ b/src/nodejs/unit-http/addon.cpp @@ -0,0 +1,15 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#include "unit.h" + + +napi_value +Init(napi_env env, napi_value exports) +{ + return Unit::init(env, exports); +} + +NAPI_MODULE(Unit, Init) diff --git a/src/nodejs/unit-http/binding.gyp b/src/nodejs/unit-http/binding.gyp new file mode 100644 index 00000000..171c2eb7 --- /dev/null +++ b/src/nodejs/unit-http/binding.gyp @@ -0,0 +1,12 @@ +{ + 'targets': [{ + 'target_name': "unit-http", + 'sources': ["unit.cpp", "addon.cpp"], + 'include_dirs': [ + " 999) { + throw new ERR_HTTP_INVALID_STATUS_CODE(originalStatusCode); + } + + if (typeof reason === 'string') { + this.statusMessage = reason; + + } else { + if (!this.statusMessage) { + this.statusMessage = http.STATUS_CODES[statusCode] || 'unknown'; + } + + obj = reason; + } + + this.statusCode = statusCode; + + if (obj) { + var k; + var keys = Object.keys(obj); + + for (var i = 0; i < keys.length; i++) { + k = keys[i]; + + if (k) { + this.setHeader(k, obj[k]); + } + } + } + + unit_lib.unit_response_headers(this, statusCode, this.headers, this.headers_count, this.headers_len); + + this.headersSent = true; +}; + +ServerResponse.prototype._writeBody = function(chunk, encoding, callback) { + var contentLength = 0; + + if (!this.headersSent) { + this.writeHead(this.statusCode); + } + + if (this.finished) { + return this; + } + + if (typeof chunk === 'function') { + callback = chunk; + chunk = null; + + } else if (typeof encoding === 'function') { + callback = encoding; + encoding = null; + } + + if (chunk) { + if (typeof chunk !== 'string' && !(chunk instanceof Buffer)) { + throw new TypeError('First argument must be a string or Buffer'); + } + + if (typeof chunk === 'string') { + contentLength = Buffer.byteLength(chunk, encoding); + + } else { + contentLength = chunk.length; + } + + unit_lib.unit_response_write(this, chunk, contentLength); + } + + if (typeof callback === 'function') { + callback(this); + } +}; + +ServerResponse.prototype.write = function write(chunk, encoding, callback) { + this._writeBody(chunk, encoding, callback); + + return this; +}; + +ServerResponse.prototype.end = function end(chunk, encoding, callback) { + this._writeBody(chunk, encoding, callback); + unit_lib.unit_response_end(this) + + this.finished = true; + + return this; +}; + +function ServerRequest(server) { + EventEmitter.call(this); + + this.server = server; +} +util.inherits(ServerRequest, EventEmitter); + +ServerRequest.prototype.unpipe = undefined; + +ServerRequest.prototype.setTimeout = function setTimeout(msecs, callback) { + this.timeout = msecs; + + if (callback) { + this.on('timeout', callback); + } + + return this; +}; + +ServerRequest.prototype.statusCode = function statusCode() { + /* Only valid for response obtained from http.ClientRequest. */ +}; + +ServerRequest.prototype.statusMessage = function statusMessage() { + /* Only valid for response obtained from http.ClientRequest. */ +}; + +ServerRequest.prototype.trailers = function trailers() { + throw new Error("Not supported"); +}; + +ServerRequest.prototype.METHODS = function METHODS() { + return http.METHODS; +}; + +ServerRequest.prototype.STATUS_CODES = function STATUS_CODES() { + return http.STATUS_CODES; +}; + +ServerRequest.prototype.listeners = function listeners() { + return []; +}; + +ServerRequest.prototype.resume = function resume() { + return []; +}; + +function Server(requestListener) { + EventEmitter.call(this); + + this.unit = new unit_lib.Unit(); + this.unit.createServer(); + + this.unit.server = this; + + this.socket = Socket; + this.request = ServerRequest; + this.response = ServerResponse; + + if (requestListener) { + this.on('request', requestListener); + } +} +util.inherits(Server, EventEmitter); + +Server.prototype.setTimeout = function setTimeout(msecs, callback) { + this.timeout = msecs; + + if (callback) { + this.on('timeout', callback); + } + + return this; +}; + +Server.prototype.listen = function () { + this.unit.listen(); +}; + +function connectionListener(socket) { +} + + +module.exports = { + STATUS_CODES: http.STATUS_CODES, + Server, + ServerResponse, + ServerRequest, + _connectionListener: connectionListener +}; diff --git a/src/nodejs/unit-http/package.json b/src/nodejs/unit-http/package.json new file mode 100644 index 00000000..bc481bc9 --- /dev/null +++ b/src/nodejs/unit-http/package.json @@ -0,0 +1,29 @@ +{ + "name": "unit-http", + "version": "1.0.0", + "description": "HTTP module for NGINX Unit", + "main": "http.js", + "files": [ + "addon.cpp", + "binding.gyp", + "http_server.js", + "http.js", + "package.json", + "socket.js", + "unit.cpp", + "unit.h", + "README.md" + ], + "scripts": { + "clean": "node-gyp clean", + "configure": "node-gyp configure", + "build": "node-gyp build", + "install": "node-gyp configure build" + }, + "author": "Alexander Borisov", + "license": "Apache 2.0", + "gypfile": true, + "dependencies": { + "node-addon-api": "1.2.0" + } +} diff --git a/src/nodejs/unit-http/socket.js b/src/nodejs/unit-http/socket.js new file mode 100755 index 00000000..89702834 --- /dev/null +++ b/src/nodejs/unit-http/socket.js @@ -0,0 +1,99 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +'use strict'; + +const EventEmitter = require('events'); +const util = require('util'); +const unit_lib = require('unit-http/build/Release/unit-http.node'); + +function Socket(options) { + EventEmitter.call(this); + + if (typeof options === 'number') { + options = { fd: options }; + + } else if (options === undefined) { + options = {}; + } + + this.readable = options.readable !== false; + this.writable = options.writable !== false; +} +util.inherits(Socket, EventEmitter); + +Socket.prototype.bufferSize = 0; +Socket.prototype.bytesRead = 0; +Socket.prototype.bytesWritten = 0; +Socket.prototype.connecting = false; +Socket.prototype.destroyed = false; +Socket.prototype.localAddress = ""; +Socket.prototype.localPort = 0; +Socket.prototype.remoteAddress = ""; +Socket.prototype.remoteFamily = ""; +Socket.prototype.remotePort = 0; + +Socket.prototype.address = function address() { +}; + +Socket.prototype.connect = function connect(options, callback) { + if (callback !== null) { + this.once('connect', cb); + } + + this.connecting = true; + this.writable = true; +}; + +Socket.prototype.address = function address() { +}; + +Socket.prototype.destroy = function destroy(exception) { + this.connecting = false; + this.readable = false; + this.writable = false; +}; + +Socket.prototype.end = function end(data, encoding) { +}; + +Socket.prototype.pause = function pause() { +}; + +Socket.prototype.ref = function ref() { +}; + +Socket.prototype.resume = function resume() { +}; + +Socket.prototype.setEncoding = function setEncoding(encoding) { +}; + +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); + } + + return this; +}; + +Socket.prototype.unref = function unref() { +}; + +Socket.prototype.write = function write(data, encoding, callback) { +}; + + +module.exports = { + Socket +}; diff --git a/src/nodejs/unit-http/unit.cpp b/src/nodejs/unit-http/unit.cpp new file mode 100644 index 00000000..40f641a6 --- /dev/null +++ b/src/nodejs/unit-http/unit.cpp @@ -0,0 +1,905 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#include "unit.h" + + +napi_ref Unit::constructor_; + + +Unit::Unit(napi_env env): + env_(env), + wrapper_(nullptr), + unit_ctx_(nullptr) +{ +} + + +Unit::~Unit() +{ + napi_delete_reference(env_, wrapper_); +} + + +napi_value +Unit::init(napi_env env, napi_value exports) +{ + napi_value cons, fn; + napi_status status; + + napi_property_descriptor properties[] = { + { "createServer", 0, create_server, 0, 0, 0, napi_default, 0 }, + { "listen", 0, listen, 0, 0, 0, napi_default, 0 } + }; + + status = napi_define_class(env, "Unit", NAPI_AUTO_LENGTH, create, nullptr, + 2, properties, &cons); + if (status != napi_ok) { + goto failed; + } + + status = napi_create_reference(env, cons, 1, &constructor_); + if (status != napi_ok) { + goto failed; + } + + status = napi_set_named_property(env, exports, "Unit", cons); + if (status != napi_ok) { + goto failed; + } + + status = napi_create_function(env, NULL, 0, response_send_headers, NULL, + &fn); + if (status != napi_ok) { + goto failed; + } + + status = napi_set_named_property(env, exports, + "unit_response_headers", fn); + if (status != napi_ok) { + goto failed; + } + + status = napi_create_function(env, NULL, 0, response_write, NULL, &fn); + if (status != napi_ok) { + goto failed; + } + + status = napi_set_named_property(env, exports, "unit_response_write", fn); + if (status != napi_ok) { + goto failed; + } + + status = napi_create_function(env, NULL, 0, response_end, NULL, &fn); + if (status != napi_ok) { + goto failed; + } + + status = napi_set_named_property(env, exports, "unit_response_end", fn); + if (status != napi_ok) { + goto failed; + } + + return exports; + +failed: + + napi_throw_error(env, NULL, "Failed to define Unit class"); + + return nullptr; +} + + +void +Unit::destroy(napi_env env, void *nativeObject, void *finalize_hint) +{ + Unit *obj = reinterpret_cast(nativeObject); + + delete obj; +} + + +napi_value +Unit::create(napi_env env, napi_callback_info info) +{ + Unit *obj; + napi_value target, cons, instance, jsthis; + napi_status status; + + status = napi_get_new_target(env, info, &target); + if (status != napi_ok) { + goto failed; + } + + if (target != nullptr) { + /* Invoked as constructor: `new Unit(...)` */ + status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, + nullptr); + if (status != napi_ok) { + goto failed; + } + + obj = new Unit(env); + + status = napi_wrap(env, jsthis, reinterpret_cast(obj), + destroy, nullptr, &obj->wrapper_); + if (status != napi_ok) { + goto failed; + } + + return jsthis; + } + + /* Invoked as plain function `Unit(...)`, turn into construct call. */ + status = napi_get_reference_value(env, constructor_, &cons); + if (status != napi_ok) { + goto failed; + } + + status = napi_new_instance(env, cons, 0, nullptr, &instance); + if (status != napi_ok) { + goto failed; + } + + return instance; + +failed: + + napi_throw_error(env, NULL, "Failed to create Unit object"); + + return nullptr; +} + + +napi_value +Unit::create_server(napi_env env, napi_callback_info info) +{ + Unit *obj; + size_t argc; + napi_value jsthis; + 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); + if (status != napi_ok) { + goto failed; + } + + status = napi_unwrap(env, jsthis, reinterpret_cast(&obj)); + if (status != napi_ok) { + goto failed; + } + + memset(&unit_init, 0, sizeof(nxt_unit_init_t)); + + unit_init.data = obj; + unit_init.callbacks.request_handler = request_handler; + + obj->unit_ctx_ = nxt_unit_init(&unit_init); + if (obj->unit_ctx_ == NULL) { + goto failed; + } + + return nullptr; + +failed: + + napi_throw_error(env, NULL, "Failed to create Unit object"); + + return nullptr; +} + + +napi_value +Unit::listen(napi_env env, napi_callback_info info) +{ + int ret; + Unit *obj; + napi_value jsthis; + napi_status status; + + status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr); + if (status != napi_ok) { + goto failed; + } + + 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"); + return nullptr; + } + + ret = nxt_unit_run(obj->unit_ctx_); + if (ret != NXT_UNIT_OK) { + napi_throw_error(env, NULL, "Failed to run Unit"); + return nullptr; + } + + nxt_unit_done(obj->unit_ctx_); + + return nullptr; + +failed: + + napi_throw_error(env, NULL, "Failed to listen Unit socket"); + + return nullptr; +} + + +void +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_status status; + + obj = reinterpret_cast(req->unit->data); + + napi_handle_scope scope; + status = napi_open_handle_scope(obj->env_, &scope); + if (status != napi_ok) { + napi_throw_error(obj->env_, NULL, "Failed to create handle scope"); + return; + } + + server_obj = obj->get_server_object(); + if (server_obj == nullptr) { + napi_throw_error(obj->env_, NULL, "Failed to get server object"); + return; + } + + status = napi_get_global(obj->env_, &global); + if (status != napi_ok) { + napi_throw_error(obj->env_, NULL, "Failed to get global variable"); + return; + } + + socket = obj->create_socket(server_obj, req); + if (socket == nullptr) { + napi_throw_error(obj->env_, NULL, "Failed to create socket object"); + return; + } + + request = obj->create_request(server_obj, socket); + if (request == nullptr) { + napi_throw_error(obj->env_, NULL, "Failed to create request object"); + return; + } + + response = obj->create_response(server_obj, socket, request, req, obj); + if (response == nullptr) { + napi_throw_error(obj->env_, NULL, "Failed to create response object"); + 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); + + napi_close_handle_scope(obj->env_, scope); +} + + +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_get_named_property(env_, unit_obj, "server", &server_obj); + if (status != napi_ok) { + return nullptr; + } + + return server_obj; +} + + +napi_value +Unit::emit(napi_value obj, const char *name, size_t name_len, size_t argc, + napi_value *argv) +{ + napi_value emitter, return_val, str; + napi_status status; + + status = napi_get_named_property(env_, obj, "emit", &emitter); + if (status != napi_ok) { + return nullptr; + } + + status = napi_create_string_latin1(env_, name, name_len, &str); + if (status != napi_ok) { + return nullptr; + } + + if (argc != 0) { + argv[0] = str; + + } else { + argc = 1; + argv = &str; + } + + status = napi_call_function(env_, obj, emitter, argc, argv, &return_val); + if (status != napi_ok) { + return nullptr; + } + + return return_val; +} + + +napi_status +Unit::create_headers(nxt_unit_request_info_t *req, napi_value request) +{ + uint32_t i; + const char *p; + napi_value headers, raw_headers, str; + napi_status status; + nxt_unit_field_t *f; + nxt_unit_request_t *r; + + r = req->request; + + status = napi_create_object(env_, &headers); + if (status != napi_ok) { + return status; + } + + status = napi_create_array_with_length(env_, r->fields_count * 2, + &raw_headers); + if (status != napi_ok) { + return status; + } + + for (i = 0; i < r->fields_count; i++) { + f = r->fields + i; + + status = this->append_header(f, headers, raw_headers, i); + if (status != napi_ok) { + return status; + } + } + + status = napi_set_named_property(env_, request, "headers", headers); + if (status != napi_ok) { + return status; + } + + status = napi_set_named_property(env_, request, "raw_headers", raw_headers); + if (status != napi_ok) { + return status; + } + + p = (const char *) nxt_unit_sptr_get(&r->version); + + status = napi_create_string_latin1(env_, p, r->version_length, &str); + if (status != napi_ok) { + return status; + } + + status = napi_set_named_property(env_, request, "httpVersion", str); + if (status != napi_ok) { + return status; + } + + p = (const char *) nxt_unit_sptr_get(&r->method); + + status = napi_create_string_latin1(env_, p, r->method_length, &str); + if (status != napi_ok) { + return status; + } + + status = napi_set_named_property(env_, request, "method", str); + if (status != napi_ok) { + return status; + } + + p = (const char *) nxt_unit_sptr_get(&r->target); + + status = napi_create_string_latin1(env_, p, r->target_length, &str); + if (status != napi_ok) { + return status; + } + + status = napi_set_named_property(env_, request, "url", str); + if (status != napi_ok) { + return status; + } + + return napi_ok; +} + + +inline napi_status +Unit::append_header(nxt_unit_field_t *f, napi_value headers, + napi_value raw_headers, uint32_t idx) +{ + const char *name, *value; + napi_value str, vstr; + napi_status status; + + value = (const char *) nxt_unit_sptr_get(&f->value); + + status = napi_create_string_latin1(env_, value, f->value_length, &vstr); + if (status != napi_ok) { + return status; + } + + name = (const char *) nxt_unit_sptr_get(&f->name); + + status = napi_set_named_property(env_, headers, name, vstr); + if (status != napi_ok) { + return status; + } + + status = napi_create_string_latin1(env_, name, f->name_length, &str); + if (status != napi_ok) { + return status; + } + + status = napi_set_element(env_, raw_headers, idx * 2, str); + if (status != napi_ok) { + return status; + } + + status = napi_set_element(env_, raw_headers, idx * 2 + 1, vstr); + if (status != napi_ok) { + return status; + } + + return napi_ok; +} + + +napi_value +Unit::create_socket(napi_value server_obj, nxt_unit_request_info_t *req) +{ + napi_value constructor, return_val; + napi_status status; + + status = napi_get_named_property(env_, server_obj, "socket", + &constructor); + if (status != napi_ok) { + return nullptr; + } + + status = napi_new_instance(env_, constructor, 0, NULL, &return_val); + if (status != napi_ok) { + return nullptr; + } + + return return_val; +} + + +napi_value +Unit::create_request(napi_value server_obj, napi_value socket) +{ + napi_value constructor, return_val; + napi_status status; + + status = napi_get_named_property(env_, server_obj, "request", + &constructor); + if (status != napi_ok) { + return nullptr; + } + + status = napi_new_instance(env_, constructor, 1, &server_obj, + &return_val); + if (status != napi_ok) { + return nullptr; + } + + status = napi_set_named_property(env_, return_val, "socket", socket); + if (status != napi_ok) { + return nullptr; + } + + return return_val; +} + + +napi_value +Unit::create_response(napi_value server_obj, napi_value socket, + napi_value request, nxt_unit_request_info_t *req, + Unit *obj) +{ + napi_value constructor, return_val, req_num; + napi_status status; + + status = napi_get_named_property(env_, server_obj, "response", + &constructor); + if (status != napi_ok) { + return nullptr; + } + + status = napi_new_instance(env_, constructor, 1, &request, &return_val); + if (status != napi_ok) { + return nullptr; + } + + status = napi_set_named_property(env_, return_val, "socket", socket); + if (status != napi_ok) { + return nullptr; + } + + status = napi_create_int64(env_, (int64_t) (uintptr_t) req, &req_num); + if (status != napi_ok) { + return nullptr; + } + + status = napi_set_named_property(env_, return_val, "_req_point", req_num); + if (status != napi_ok) { + return nullptr; + } + + return return_val; +} + + +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) +{ + int ret; + char *ptr, *name_ptr; + bool is_array; + size_t argc, name_len, value_len; + int64_t req_p; + uint32_t status_code, header_len, keys_len, array_len; + uint32_t keys_count, i, j; + uint16_t hash; + napi_value this_arg, headers, keys, name, value, array_val; + napi_value req_num; + napi_status status; + nxt_unit_field_t *f; + nxt_unit_request_info_t *req; + napi_value argv[5]; + + argc = 5; + + status = napi_get_cb_info(env, info, &argc, argv, &this_arg, NULL); + if (status != napi_ok) { + return nullptr; + } + + if (argc != 5) { + napi_throw_error(env, NULL, "Wrong args count. Need three: " + "statusCode, headers, headers count, headers length"); + return nullptr; + } + + status = napi_get_named_property(env, argv[0], "_req_point", &req_num); + if (status != napi_ok) { + napi_throw_error(env, NULL, "Failed to get request pointer"); + return nullptr; + } + + status = napi_get_value_int64(env, req_num, &req_p); + if (status != napi_ok) { + napi_throw_error(env, NULL, "Failed to get request pointer"); + return nullptr; + } + + req = (nxt_unit_request_info_t *) (uintptr_t) req_p; + + status = napi_get_value_uint32(env, argv[1], &status_code); + if (status != napi_ok) { + goto failed; + } + + status = napi_get_value_uint32(env, argv[3], &keys_count); + if (status != napi_ok) { + goto failed; + } + + status = napi_get_value_uint32(env, argv[4], &header_len); + if (status != napi_ok) { + goto failed; + } + + /* Need to reserve extra byte for C-string 0-termination. */ + header_len++; + + headers = argv[2]; + + ret = nxt_unit_response_init(req, status_code, keys_count, header_len); + if (ret != NXT_UNIT_OK) { + goto failed; + } + + status = napi_get_property_names(env, headers, &keys); + if (status != napi_ok) { + goto failed; + } + + status = napi_get_array_length(env, keys, &keys_len); + if (status != napi_ok) { + goto failed; + } + + ptr = req->response_buf->free; + + for (i = 0; i < keys_len; i++) { + status = napi_get_element(env, keys, i, &name); + if (status != napi_ok) { + goto failed; + } + + status = napi_get_property(env, headers, name, &value); + if (status != napi_ok) { + goto failed; + } + + status = napi_get_value_string_latin1(env, name, ptr, header_len, + &name_len); + if (status != napi_ok) { + goto failed; + } + + name_ptr = ptr; + + ptr += name_len; + header_len -= name_len; + + hash = nxt_unit_field_hash(name_ptr, name_len); + + status = napi_is_array(env, value, &is_array); + if (status != napi_ok) { + goto failed; + } + + if (is_array) { + status = napi_get_array_length(env, value, &array_len); + if (status != napi_ok) { + goto failed; + } + + for (j = 0; j < array_len; j++) { + status = napi_get_element(env, value, j, &array_val); + if (status != napi_ok) { + goto failed; + } + + status = napi_get_value_string_latin1(env, array_val, ptr, + header_len, + &value_len); + if (status != napi_ok) { + goto failed; + } + + f = req->response->fields + req->response->fields_count; + f->skip = 0; + + nxt_unit_sptr_set(&f->name, name_ptr); + + f->name_length = name_len; + f->hash = hash; + + nxt_unit_sptr_set(&f->value, ptr); + f->value_length = (uint32_t) value_len; + + ptr += value_len; + header_len -= value_len; + + req->response->fields_count++; + } + + } else { + status = napi_get_value_string_latin1(env, value, ptr, header_len, + &value_len); + if (status != napi_ok) { + goto failed; + } + + f = req->response->fields + req->response->fields_count; + f->skip = 0; + + nxt_unit_sptr_set(&f->name, name_ptr); + + f->name_length = name_len; + f->hash = hash; + + nxt_unit_sptr_set(&f->value, ptr); + f->value_length = (uint32_t) value_len; + + ptr += value_len; + header_len -= value_len; + + req->response->fields_count++; + } + } + + req->response_buf->free = ptr; + + ret = nxt_unit_response_send(req); + if (ret != NXT_UNIT_OK) { + goto failed; + } + + return this_arg; + +failed: + + req->response->fields_count = 0; + + napi_throw_error(env, NULL, "Failed to write headers"); + + return nullptr; +} + + +napi_value +Unit::response_write(napi_env env, napi_callback_info info) +{ + int ret; + char *ptr; + size_t argc, have_buf_len; + int64_t req_p; + uint32_t buf_len; + napi_value this_arg, req_num; + napi_status status; + nxt_unit_buf_t *buf; + napi_valuetype buf_type; + nxt_unit_request_info_t *req; + napi_value argv[3]; + + argc = 3; + + status = napi_get_cb_info(env, info, &argc, argv, &this_arg, NULL); + if (status != napi_ok) { + goto failed; + } + + if (argc != 3) { + napi_throw_error(env, NULL, "Wrong args count. Need two: " + "chunk, chunk length"); + return nullptr; + } + + status = napi_get_named_property(env, argv[0], "_req_point", &req_num); + if (status != napi_ok) { + napi_throw_error(env, NULL, "Failed to get request pointer"); + return nullptr; + } + + status = napi_get_value_int64(env, req_num, &req_p); + if (status != napi_ok) { + napi_throw_error(env, NULL, "Failed to get request pointer"); + return nullptr; + } + + req = (nxt_unit_request_info_t *) (uintptr_t) req_p; + + status = napi_get_value_uint32(env, argv[2], &buf_len); + if (status != napi_ok) { + goto failed; + } + + status = napi_typeof(env, argv[1], &buf_type); + if (status != napi_ok) { + goto failed; + } + + buf_len++; + + buf = nxt_unit_response_buf_alloc(req, buf_len); + if (buf == NULL) { + goto failed; + } + + if (buf_type == napi_string) { + /* TODO: will work only for utf8 content-type */ + + status = napi_get_value_string_utf8(env, argv[1], buf->free, + buf_len, &have_buf_len); + + } else { + status = napi_get_buffer_info(env, argv[1], (void **) &ptr, + &have_buf_len); + + memcpy(buf->free, ptr, have_buf_len); + } + + if (status != napi_ok) { + goto failed; + } + + buf->free += have_buf_len; + + ret = nxt_unit_buf_send(buf); + if (ret != NXT_UNIT_OK) { + goto failed; + } + + return this_arg; + +failed: + + napi_throw_error(env, NULL, "Failed to write body"); + + return nullptr; +} + + +napi_value +Unit::response_end(napi_env env, napi_callback_info info) +{ + size_t argc; + int64_t req_p; + napi_value resp, this_arg, req_num; + napi_status status; + nxt_unit_request_info_t *req; + + argc = 1; + + status = napi_get_cb_info(env, info, &argc, &resp, &this_arg, NULL); + if (status != napi_ok) { + napi_throw_error(env, NULL, "Failed to finalize sending body"); + return nullptr; + } + + status = napi_get_named_property(env, resp, "_req_point", &req_num); + if (status != napi_ok) { + napi_throw_error(env, NULL, "Failed to get request pointer"); + return nullptr; + } + + status = napi_get_value_int64(env, req_num, &req_p); + if (status != napi_ok) { + napi_throw_error(env, NULL, "Failed to get request pointer"); + return nullptr; + } + + req = (nxt_unit_request_info_t *) (uintptr_t) req_p; + + nxt_unit_request_done(req, NXT_UNIT_OK); + + return this_arg; +} diff --git a/src/nodejs/unit-http/unit.h b/src/nodejs/unit-http/unit.h new file mode 100644 index 00000000..753a14d8 --- /dev/null +++ b/src/nodejs/unit-http/unit.h @@ -0,0 +1,77 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_NODEJS_UNIT_H_INCLUDED_ +#define _NXT_NODEJS_UNIT_H_INCLUDED_ + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +class Unit { +public: + static napi_value init(napi_env env, napi_value exports); + +private: + Unit(napi_env env); + ~Unit(); + + static napi_value create(napi_env env, napi_callback_info info); + static void destroy(napi_env env, void *nativeObject, void *finalize_hint); + + static napi_value create_server(napi_env env, napi_callback_info info); + static napi_value listen(napi_env env, napi_callback_info info); + static void request_handler(nxt_unit_request_info_t *req); + + 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); + + napi_value create_request(napi_value server_obj, napi_value socket); + + napi_value create_response(napi_value server_obj, napi_value socket, + 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); + + static napi_value response_write(napi_env env, napi_callback_info info); + static napi_value response_end(napi_env env, napi_callback_info info); + + napi_status create_headers(nxt_unit_request_info_t *req, + napi_value request); + + inline napi_status append_header(nxt_unit_field_t *f, napi_value headers, + napi_value raw_headers, uint32_t idx); + + static napi_ref constructor_; + + napi_env env_; + napi_ref wrapper_; + nxt_unit_ctx_t *unit_ctx_; +}; + + +#endif /* _NXT_NODEJS_H_INCLUDED_ */ -- cgit From 6c5e5f25ef74dbf4d3dc524e293863fad7fcf524 Mon Sep 17 00:00:00 2001 From: Andrei Belov Date: Fri, 5 Oct 2018 14:10:13 +0300 Subject: Packages: all CRLF newlines in examples converted to LF. --- pkg/deb/debian.module/unit.example-go-config | 30 +++---- pkg/deb/debian.module/unit.example-go1.10-config | 30 +++---- pkg/deb/debian.module/unit.example-go1.7-config | 30 +++---- pkg/deb/debian.module/unit.example-go1.8-config | 30 +++---- pkg/deb/debian.module/unit.example-go1.9-config | 30 +++---- pkg/deb/debian/unit.example.config | 102 +++++++++++------------ 6 files changed, 126 insertions(+), 126 deletions(-) diff --git a/pkg/deb/debian.module/unit.example-go-config b/pkg/deb/debian.module/unit.example-go-config index 6ee4d001..d6a2a8a0 100644 --- a/pkg/deb/debian.module/unit.example-go-config +++ b/pkg/deb/debian.module/unit.example-go-config @@ -1,15 +1,15 @@ -{ - "applications": { - "example_go": { - "type": "go", - "user": "nobody", - "executable": "/tmp/go-app" - } - }, - - "listeners": { - "*:8500": { - "application": "example_go" - } - } -} +{ + "applications": { + "example_go": { + "type": "go", + "user": "nobody", + "executable": "/tmp/go-app" + } + }, + + "listeners": { + "*:8500": { + "application": "example_go" + } + } +} diff --git a/pkg/deb/debian.module/unit.example-go1.10-config b/pkg/deb/debian.module/unit.example-go1.10-config index 68733256..262eae29 100644 --- a/pkg/deb/debian.module/unit.example-go1.10-config +++ b/pkg/deb/debian.module/unit.example-go1.10-config @@ -1,15 +1,15 @@ -{ - "applications": { - "example_go": { - "type": "go", - "user": "nobody", - "executable": "/tmp/go1.10-app" - } - }, - - "listeners": { - "*:8500": { - "application": "example_go" - } - } -} +{ + "applications": { + "example_go": { + "type": "go", + "user": "nobody", + "executable": "/tmp/go1.10-app" + } + }, + + "listeners": { + "*:8500": { + "application": "example_go" + } + } +} diff --git a/pkg/deb/debian.module/unit.example-go1.7-config b/pkg/deb/debian.module/unit.example-go1.7-config index 1b1943e0..62489959 100644 --- a/pkg/deb/debian.module/unit.example-go1.7-config +++ b/pkg/deb/debian.module/unit.example-go1.7-config @@ -1,15 +1,15 @@ -{ - "applications": { - "example_go": { - "type": "go", - "user": "nobody", - "executable": "/tmp/go1.7-app" - } - }, - - "listeners": { - "*:8500": { - "application": "example_go" - } - } -} +{ + "applications": { + "example_go": { + "type": "go", + "user": "nobody", + "executable": "/tmp/go1.7-app" + } + }, + + "listeners": { + "*:8500": { + "application": "example_go" + } + } +} diff --git a/pkg/deb/debian.module/unit.example-go1.8-config b/pkg/deb/debian.module/unit.example-go1.8-config index 6cfa0cec..551ec24e 100644 --- a/pkg/deb/debian.module/unit.example-go1.8-config +++ b/pkg/deb/debian.module/unit.example-go1.8-config @@ -1,15 +1,15 @@ -{ - "applications": { - "example_go": { - "type": "go", - "user": "nobody", - "executable": "/tmp/go1.8-app" - } - }, - - "listeners": { - "*:8500": { - "application": "example_go" - } - } -} +{ + "applications": { + "example_go": { + "type": "go", + "user": "nobody", + "executable": "/tmp/go1.8-app" + } + }, + + "listeners": { + "*:8500": { + "application": "example_go" + } + } +} diff --git a/pkg/deb/debian.module/unit.example-go1.9-config b/pkg/deb/debian.module/unit.example-go1.9-config index 4074df3b..ab026fb3 100644 --- a/pkg/deb/debian.module/unit.example-go1.9-config +++ b/pkg/deb/debian.module/unit.example-go1.9-config @@ -1,15 +1,15 @@ -{ - "applications": { - "example_go": { - "type": "go", - "user": "nobody", - "executable": "/tmp/go1.9-app" - } - }, - - "listeners": { - "*:8500": { - "application": "example_go" - } - } -} +{ + "applications": { + "example_go": { + "type": "go", + "user": "nobody", + "executable": "/tmp/go1.9-app" + } + }, + + "listeners": { + "*:8500": { + "application": "example_go" + } + } +} diff --git a/pkg/deb/debian/unit.example.config b/pkg/deb/debian/unit.example.config index f3126457..a4396a58 100644 --- a/pkg/deb/debian/unit.example.config +++ b/pkg/deb/debian/unit.example.config @@ -1,51 +1,51 @@ -{ - "applications": { - "example_php": { - "type": "php", - "user": "nobody", - "processes": 2, - "root": "/usr/share/doc/unit/examples/php-app", - "index": "index.php" - }, - - "example_python": { - "type": "python", - "user": "nobody", - "processes": 2, - "path": "/usr/share/doc/unit/examples/python-app", - "module": "wsgi" - }, - - "example_go": { - "type": "go", - "user": "nobody", - "executable": "/tmp/go-app" - }, - - "example_perl": { - "type": "perl", - "user": "nobody", - "processes": 1, - "working_directory": "/usr/share/doc/unit-perl/examples/perl-app", - "script": "/usr/share/doc/unit-perl/examples/perl-app/index.pl" - } - }, - - "listeners": { - "*:8300": { - "application": "example_php" - }, - - "*:8400": { - "application": "example_python" - }, - - "*:8500": { - "application": "example_go" - }, - - "*:8600": { - "application": "example_perl" - } - } -} +{ + "applications": { + "example_php": { + "type": "php", + "user": "nobody", + "processes": 2, + "root": "/usr/share/doc/unit/examples/php-app", + "index": "index.php" + }, + + "example_python": { + "type": "python", + "user": "nobody", + "processes": 2, + "path": "/usr/share/doc/unit/examples/python-app", + "module": "wsgi" + }, + + "example_go": { + "type": "go", + "user": "nobody", + "executable": "/tmp/go-app" + }, + + "example_perl": { + "type": "perl", + "user": "nobody", + "processes": 1, + "working_directory": "/usr/share/doc/unit-perl/examples/perl-app", + "script": "/usr/share/doc/unit-perl/examples/perl-app/index.pl" + } + }, + + "listeners": { + "*:8300": { + "application": "example_php" + }, + + "*:8400": { + "application": "example_python" + }, + + "*:8500": { + "application": "example_go" + }, + + "*:8600": { + "application": "example_perl" + } + } +} -- cgit From 029c1a9f509b2af60e02d74ef982fda1346d85e0 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Tue, 9 Oct 2018 17:53:31 +0300 Subject: Renamed "go" application type to "external". There's nothing specific to Go language. This type of application object can be used to run any external application that utilizes libunit API. --- auto/sources | 2 +- pkg/deb/debian.module/unit.example-go-config | 2 +- pkg/deb/debian.module/unit.example-go1.10-config | 2 +- pkg/deb/debian.module/unit.example-go1.7-config | 2 +- pkg/deb/debian.module/unit.example-go1.8-config | 2 +- pkg/deb/debian.module/unit.example-go1.9-config | 2 +- pkg/deb/debian/unit.example.config | 2 +- pkg/rpm/rpmbuild/SOURCES/unit.example-go-config | 2 +- pkg/rpm/rpmbuild/SOURCES/unit.example.config | 2 +- src/nxt_application.c | 8 +- src/nxt_application.h | 26 ++-- src/nxt_conf_validation.c | 32 ++-- src/nxt_external.c | 178 +++++++++++++++++++++++ src/nxt_go.c | 175 ---------------------- src/nxt_main_process.c | 42 +++--- src/nxt_router.c | 2 +- src/nxt_runtime.c | 4 +- test/unit.py | 2 +- 18 files changed, 245 insertions(+), 242 deletions(-) create mode 100644 src/nxt_external.c delete mode 100644 src/nxt_go.c diff --git a/auto/sources b/auto/sources index e7074345..0ebdab63 100644 --- a/auto/sources +++ b/auto/sources @@ -84,7 +84,7 @@ NXT_LIB_SRCS=" \ src/nxt_http_response.c \ src/nxt_http_error.c \ src/nxt_application.c \ - src/nxt_go.c \ + src/nxt_external.c \ src/nxt_port_hash.c \ " diff --git a/pkg/deb/debian.module/unit.example-go-config b/pkg/deb/debian.module/unit.example-go-config index d6a2a8a0..079ce0b8 100644 --- a/pkg/deb/debian.module/unit.example-go-config +++ b/pkg/deb/debian.module/unit.example-go-config @@ -1,7 +1,7 @@ { "applications": { "example_go": { - "type": "go", + "type": "external", "user": "nobody", "executable": "/tmp/go-app" } diff --git a/pkg/deb/debian.module/unit.example-go1.10-config b/pkg/deb/debian.module/unit.example-go1.10-config index 262eae29..29bb9059 100644 --- a/pkg/deb/debian.module/unit.example-go1.10-config +++ b/pkg/deb/debian.module/unit.example-go1.10-config @@ -1,7 +1,7 @@ { "applications": { "example_go": { - "type": "go", + "type": "external", "user": "nobody", "executable": "/tmp/go1.10-app" } diff --git a/pkg/deb/debian.module/unit.example-go1.7-config b/pkg/deb/debian.module/unit.example-go1.7-config index 62489959..bd98fe3a 100644 --- a/pkg/deb/debian.module/unit.example-go1.7-config +++ b/pkg/deb/debian.module/unit.example-go1.7-config @@ -1,7 +1,7 @@ { "applications": { "example_go": { - "type": "go", + "type": "external", "user": "nobody", "executable": "/tmp/go1.7-app" } diff --git a/pkg/deb/debian.module/unit.example-go1.8-config b/pkg/deb/debian.module/unit.example-go1.8-config index 551ec24e..1c14ca25 100644 --- a/pkg/deb/debian.module/unit.example-go1.8-config +++ b/pkg/deb/debian.module/unit.example-go1.8-config @@ -1,7 +1,7 @@ { "applications": { "example_go": { - "type": "go", + "type": "external", "user": "nobody", "executable": "/tmp/go1.8-app" } diff --git a/pkg/deb/debian.module/unit.example-go1.9-config b/pkg/deb/debian.module/unit.example-go1.9-config index ab026fb3..341894b7 100644 --- a/pkg/deb/debian.module/unit.example-go1.9-config +++ b/pkg/deb/debian.module/unit.example-go1.9-config @@ -1,7 +1,7 @@ { "applications": { "example_go": { - "type": "go", + "type": "external", "user": "nobody", "executable": "/tmp/go1.9-app" } diff --git a/pkg/deb/debian/unit.example.config b/pkg/deb/debian/unit.example.config index a4396a58..8d86acbe 100644 --- a/pkg/deb/debian/unit.example.config +++ b/pkg/deb/debian/unit.example.config @@ -17,7 +17,7 @@ }, "example_go": { - "type": "go", + "type": "external", "user": "nobody", "executable": "/tmp/go-app" }, diff --git a/pkg/rpm/rpmbuild/SOURCES/unit.example-go-config b/pkg/rpm/rpmbuild/SOURCES/unit.example-go-config index d6a2a8a0..079ce0b8 100644 --- a/pkg/rpm/rpmbuild/SOURCES/unit.example-go-config +++ b/pkg/rpm/rpmbuild/SOURCES/unit.example-go-config @@ -1,7 +1,7 @@ { "applications": { "example_go": { - "type": "go", + "type": "external", "user": "nobody", "executable": "/tmp/go-app" } diff --git a/pkg/rpm/rpmbuild/SOURCES/unit.example.config b/pkg/rpm/rpmbuild/SOURCES/unit.example.config index a5f31ced..1715c971 100644 --- a/pkg/rpm/rpmbuild/SOURCES/unit.example.config +++ b/pkg/rpm/rpmbuild/SOURCES/unit.example.config @@ -17,7 +17,7 @@ }, "example_go": { - "type": "go", + "type": "external", "user": "nobody", "executable": "/tmp/go-app" }, diff --git a/src/nxt_application.c b/src/nxt_application.c index 3c62f7d4..acdebe04 100644 --- a/src/nxt_application.c +++ b/src/nxt_application.c @@ -507,15 +507,15 @@ nxt_app_parse_type(u_char *p, size_t length) str.length = length; str.start = p; - if (nxt_str_eq(&str, "python", 6)) { + if (nxt_str_eq(&str, "external", 8) || nxt_str_eq(&str, "go", 2)) { + return NXT_APP_EXTERNAL; + + } else if (nxt_str_eq(&str, "python", 6)) { return NXT_APP_PYTHON; } else if (nxt_str_eq(&str, "php", 3)) { return NXT_APP_PHP; - } else if (nxt_str_eq(&str, "go", 2)) { - return NXT_APP_GO; - } else if (nxt_str_eq(&str, "perl", 4)) { return NXT_APP_PERL; diff --git a/src/nxt_application.h b/src/nxt_application.h index 35346655..10f5a922 100644 --- a/src/nxt_application.h +++ b/src/nxt_application.h @@ -15,9 +15,9 @@ typedef enum { + NXT_APP_EXTERNAL, NXT_APP_PYTHON, NXT_APP_PHP, - NXT_APP_GO, NXT_APP_PERL, NXT_APP_RUBY, @@ -39,6 +39,12 @@ typedef struct { typedef struct nxt_common_app_conf_s nxt_common_app_conf_t; +typedef struct { + char *executable; + nxt_conf_value_t *arguments; +} nxt_external_app_conf_t; + + typedef struct { char *home; nxt_str_t path; @@ -54,12 +60,6 @@ typedef struct { } nxt_php_app_conf_t; -typedef struct { - char *executable; - nxt_conf_value_t *arguments; -} nxt_go_app_conf_t; - - typedef struct { char *script; } nxt_perl_app_conf_t; @@ -80,11 +80,11 @@ struct nxt_common_app_conf_s { nxt_conf_value_t *environment; union { - nxt_python_app_conf_t python; - nxt_php_app_conf_t php; - nxt_go_app_conf_t go; - nxt_perl_app_conf_t perl; - nxt_ruby_app_conf_t ruby; + nxt_external_app_conf_t external; + nxt_python_app_conf_t python; + nxt_php_app_conf_t php; + nxt_perl_app_conf_t perl; + nxt_ruby_app_conf_t ruby; } u; }; @@ -161,7 +161,7 @@ nxt_app_lang_module_t *nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name); nxt_app_type_t nxt_app_parse_type(u_char *p, size_t length); NXT_EXPORT extern nxt_str_t nxt_server; -extern nxt_app_module_t nxt_go_module; +extern nxt_app_module_t nxt_external_module; NXT_EXPORT nxt_int_t nxt_unit_default_init(nxt_task_t *task, nxt_unit_init_t *init); diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index ca7107cc..b1e30955 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -256,6 +256,21 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[] = { }; +static nxt_conf_vldt_object_t nxt_conf_vldt_external_members[] = { + { nxt_string("executable"), + NXT_CONF_VLDT_STRING, + NULL, + NULL }, + + { nxt_string("arguments"), + NXT_CONF_VLDT_ARRAY, + &nxt_conf_vldt_array_iterator, + (void *) &nxt_conf_vldt_argument }, + + NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) +}; + + static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = { { nxt_string("home"), NXT_CONF_VLDT_STRING, @@ -321,21 +336,6 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_php_members[] = { }; -static nxt_conf_vldt_object_t nxt_conf_vldt_go_members[] = { - { nxt_string("executable"), - NXT_CONF_VLDT_STRING, - NULL, - NULL }, - - { nxt_string("arguments"), - NXT_CONF_VLDT_ARRAY, - &nxt_conf_vldt_array_iterator, - (void *) &nxt_conf_vldt_argument }, - - NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) -}; - - static nxt_conf_vldt_object_t nxt_conf_vldt_perl_members[] = { { nxt_string("script"), NXT_CONF_VLDT_STRING, @@ -565,9 +565,9 @@ nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name, static nxt_str_t type_str = nxt_string("type"); static void *members[] = { + nxt_conf_vldt_external_members, nxt_conf_vldt_python_members, nxt_conf_vldt_php_members, - nxt_conf_vldt_go_members, nxt_conf_vldt_perl_members, nxt_conf_vldt_ruby_members, }; diff --git a/src/nxt_external.c b/src/nxt_external.c new file mode 100644 index 00000000..c7aacffc --- /dev/null +++ b/src/nxt_external.c @@ -0,0 +1,178 @@ + +/* + * Copyright (C) Max Romanov + * Copyright (C) NGINX, Inc. + */ + +#include +#include +#include + + +static nxt_int_t nxt_external_init(nxt_task_t *task, + nxt_common_app_conf_t *conf); + + +nxt_app_module_t nxt_external_module = { + 0, + NULL, + nxt_string("external"), + "*", + nxt_external_init, +}; + + +extern char **environ; + + +nxt_inline nxt_int_t +nxt_external_fd_no_cloexec(nxt_task_t *task, nxt_socket_t fd) +{ + int res, flags; + + if (fd == -1) { + return NXT_OK; + } + + flags = fcntl(fd, F_GETFD); + + if (nxt_slow_path(flags == -1)) { + nxt_alert(task, "fcntl(%d, F_GETFD) failed %E", fd, nxt_errno); + return NXT_ERROR; + } + + flags &= ~FD_CLOEXEC; + + res = fcntl(fd, F_SETFD, flags); + + if (nxt_slow_path(res == -1)) { + nxt_alert(task, "fcntl(%d, F_SETFD) failed %E", fd, nxt_errno); + return NXT_ERROR; + } + + nxt_fd_blocking(task, fd); + + return NXT_OK; +} + + +static nxt_int_t +nxt_external_init(nxt_task_t *task, nxt_common_app_conf_t *conf) +{ + char **argv; + u_char buf[256]; + u_char *p, *end; + uint32_t index; + size_t size; + nxt_str_t str; + nxt_int_t rc; + nxt_uint_t i, argc; + nxt_port_t *my_port, *main_port; + nxt_runtime_t *rt; + nxt_conf_value_t *value; + nxt_external_app_conf_t *c; + + rt = task->thread->runtime; + + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + my_port = nxt_runtime_port_find(rt, nxt_pid, 0); + + if (nxt_slow_path(main_port == NULL || my_port == NULL)) { + return NXT_ERROR; + } + + rc = nxt_external_fd_no_cloexec(task, main_port->pair[1]); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } + + rc = nxt_external_fd_no_cloexec(task, my_port->pair[0]); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } + + end = buf + sizeof(buf); + + p = nxt_sprintf(buf, end, + "%s;%uD;" + "%PI,%ud,%d;" + "%PI,%ud,%d;" + "%d,%Z", + NXT_VERSION, my_port->process->init->stream, + main_port->pid, main_port->id, main_port->pair[1], + my_port->pid, my_port->id, my_port->pair[0], + 2); + + if (nxt_slow_path(p == end)) { + nxt_alert(task, "internal error: buffer too small for NXT_UNIT_INIT"); + + return NXT_ERROR; + } + + nxt_debug(task, "update "NXT_UNIT_INIT_ENV"=%s", buf); + + rc = setenv(NXT_UNIT_INIT_ENV, (char *) buf, 1); + if (nxt_slow_path(rc == -1)) { + nxt_alert(task, "setenv("NXT_UNIT_INIT_ENV", %s) failed %E", buf, + nxt_errno); + + return NXT_ERROR; + } + + c = &conf->u.external; + + argc = 2; + size = 0; + + if (c->arguments != NULL) { + + for (index = 0; /* void */ ; index++) { + value = nxt_conf_get_array_element(c->arguments, index); + if (value == NULL) { + break; + } + + nxt_conf_get_string(value, &str); + + size += str.length + 1; + argc++; + } + } + + argv = nxt_malloc(argc * sizeof(argv[0]) + size); + if (nxt_slow_path(argv == NULL)) { + nxt_alert(task, "failed to allocate arguments"); + return NXT_ERROR; + } + + argv[0] = c->executable; + i = 1; + + if (c->arguments != NULL) { + p = (u_char *) &argv[argc]; + + for (index = 0; /* void */ ; index++) { + value = nxt_conf_get_array_element(c->arguments, index); + if (value == NULL) { + break; + } + + argv[i++] = (char *) p; + + nxt_conf_get_string(value, &str); + + p = nxt_cpymem(p, str.start, str.length); + *p++ = '\0'; + } + } + + argv[i] = NULL; + + (void) execve(c->executable, argv, environ); + + nxt_alert(task, "execve(%s) failed %E", c->executable, nxt_errno); + + nxt_free(argv); + + return NXT_ERROR; +} diff --git a/src/nxt_go.c b/src/nxt_go.c deleted file mode 100644 index 4e7d0488..00000000 --- a/src/nxt_go.c +++ /dev/null @@ -1,175 +0,0 @@ - -/* - * Copyright (C) Max Romanov - * Copyright (C) NGINX, Inc. - */ - -#include -#include -#include - - -static nxt_int_t nxt_go_init(nxt_task_t *task, nxt_common_app_conf_t *conf); - -nxt_app_module_t nxt_go_module = { - 0, - NULL, - nxt_string("go"), - "*", - nxt_go_init, -}; - - -extern char **environ; - -nxt_inline nxt_int_t -nxt_go_fd_no_cloexec(nxt_task_t *task, nxt_socket_t fd) -{ - int res, flags; - - if (fd == -1) { - return NXT_OK; - } - - flags = fcntl(fd, F_GETFD); - - if (nxt_slow_path(flags == -1)) { - nxt_alert(task, "fcntl(%d, F_GETFD) failed %E", fd, nxt_errno); - return NXT_ERROR; - } - - flags &= ~FD_CLOEXEC; - - res = fcntl(fd, F_SETFD, flags); - - if (nxt_slow_path(res == -1)) { - nxt_alert(task, "fcntl(%d, F_SETFD) failed %E", fd, nxt_errno); - return NXT_ERROR; - } - - nxt_fd_blocking(task, fd); - - return NXT_OK; -} - - -static nxt_int_t -nxt_go_init(nxt_task_t *task, nxt_common_app_conf_t *conf) -{ - char **argv; - u_char buf[256]; - u_char *p, *end; - uint32_t index; - size_t size; - nxt_str_t str; - nxt_int_t rc; - nxt_uint_t i, argc; - nxt_port_t *my_port, *main_port; - nxt_runtime_t *rt; - nxt_conf_value_t *value; - nxt_go_app_conf_t *c; - - rt = task->thread->runtime; - - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - my_port = nxt_runtime_port_find(rt, nxt_pid, 0); - - if (nxt_slow_path(main_port == NULL || my_port == NULL)) { - return NXT_ERROR; - } - - rc = nxt_go_fd_no_cloexec(task, main_port->pair[1]); - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } - - rc = nxt_go_fd_no_cloexec(task, my_port->pair[0]); - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } - - end = buf + sizeof(buf); - - p = nxt_sprintf(buf, end, - "%s;%uD;" - "%PI,%ud,%d;" - "%PI,%ud,%d;" - "%d,%Z", - NXT_VERSION, my_port->process->init->stream, - main_port->pid, main_port->id, main_port->pair[1], - my_port->pid, my_port->id, my_port->pair[0], - 2); - - if (nxt_slow_path(p == end)) { - nxt_alert(task, "internal error: buffer too small for NXT_UNIT_INIT"); - - return NXT_ERROR; - } - - nxt_debug(task, "update "NXT_UNIT_INIT_ENV"=%s", buf); - - rc = setenv(NXT_UNIT_INIT_ENV, (char *) buf, 1); - if (nxt_slow_path(rc == -1)) { - nxt_alert(task, "setenv("NXT_UNIT_INIT_ENV", %s) failed %E", buf, - nxt_errno); - - return NXT_ERROR; - } - - c = &conf->u.go; - - argc = 2; - size = 0; - - if (c->arguments != NULL) { - - for (index = 0; /* void */ ; index++) { - value = nxt_conf_get_array_element(c->arguments, index); - if (value == NULL) { - break; - } - - nxt_conf_get_string(value, &str); - - size += str.length + 1; - argc++; - } - } - - argv = nxt_malloc(argc * sizeof(argv[0]) + size); - if (nxt_slow_path(argv == NULL)) { - nxt_alert(task, "failed to allocate arguments"); - return NXT_ERROR; - } - - argv[0] = c->executable; - i = 1; - - if (c->arguments != NULL) { - p = (u_char *) &argv[argc]; - - for (index = 0; /* void */ ; index++) { - value = nxt_conf_get_array_element(c->arguments, index); - if (value == NULL) { - break; - } - - argv[i++] = (char *) p; - - nxt_conf_get_string(value, &str); - - p = nxt_cpymem(p, str.start, str.length); - *p++ = '\0'; - } - } - - argv[i] = NULL; - - (void) execve(c->executable, argv, environ); - - nxt_alert(task, "execve(%s) failed %E", c->executable, nxt_errno); - - nxt_free(argv); - - return NXT_ERROR; -} diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c index 491b09f3..819ed44c 100644 --- a/src/nxt_main_process.c +++ b/src/nxt_main_process.c @@ -134,6 +134,22 @@ static nxt_conf_map_t nxt_common_app_conf[] = { }; +static nxt_conf_map_t nxt_external_app_conf[] = { + { + nxt_string("executable"), + NXT_CONF_MAP_CSTRZ, + offsetof(nxt_common_app_conf_t, u.external.executable), + }, + + { + nxt_string("arguments"), + NXT_CONF_MAP_PTR, + offsetof(nxt_common_app_conf_t, u.external.arguments), + }, + +}; + + static nxt_conf_map_t nxt_python_app_conf[] = { { nxt_string("home"), @@ -182,22 +198,6 @@ static nxt_conf_map_t nxt_php_app_conf[] = { }; -static nxt_conf_map_t nxt_go_app_conf[] = { - { - nxt_string("executable"), - NXT_CONF_MAP_CSTRZ, - offsetof(nxt_common_app_conf_t, u.go.executable), - }, - - { - nxt_string("arguments"), - NXT_CONF_MAP_PTR, - offsetof(nxt_common_app_conf_t, u.go.arguments), - }, - -}; - - static nxt_conf_map_t nxt_perl_app_conf[] = { { nxt_string("script"), @@ -217,11 +217,11 @@ static nxt_conf_map_t nxt_ruby_app_conf[] = { static nxt_conf_app_map_t nxt_app_maps[] = { - { nxt_nitems(nxt_python_app_conf), nxt_python_app_conf }, - { nxt_nitems(nxt_php_app_conf), nxt_php_app_conf }, - { nxt_nitems(nxt_go_app_conf), nxt_go_app_conf }, - { nxt_nitems(nxt_perl_app_conf), nxt_perl_app_conf }, - { nxt_nitems(nxt_ruby_app_conf), nxt_ruby_app_conf }, + { nxt_nitems(nxt_external_app_conf), nxt_external_app_conf }, + { nxt_nitems(nxt_python_app_conf), nxt_python_app_conf }, + { nxt_nitems(nxt_php_app_conf), nxt_php_app_conf }, + { nxt_nitems(nxt_perl_app_conf), nxt_perl_app_conf }, + { nxt_nitems(nxt_ruby_app_conf), nxt_ruby_app_conf }, }; diff --git a/src/nxt_router.c b/src/nxt_router.c index 139b2c4c..3a5382e4 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -289,9 +289,9 @@ static const nxt_str_t http_prefix = nxt_string("HTTP_"); static const nxt_str_t empty_prefix = nxt_string(""); static const nxt_str_t *nxt_app_msg_prefix[] = { + &empty_prefix, &http_prefix, &http_prefix, - &empty_prefix, &http_prefix, &http_prefix, }; diff --git a/src/nxt_runtime.c b/src/nxt_runtime.c index 311c2c08..8f20e0a0 100644 --- a/src/nxt_runtime.c +++ b/src/nxt_runtime.c @@ -80,10 +80,10 @@ nxt_runtime_create(nxt_task_t *task) /* Should not fail. */ lang = nxt_array_add(rt->languages); - lang->type = NXT_APP_GO; + lang->type = NXT_APP_EXTERNAL; lang->version = (u_char *) ""; lang->file = NULL; - lang->module = &nxt_go_module; + lang->module = &nxt_external_module; listen_sockets = nxt_array_create(mp, 1, sizeof(nxt_listen_socket_t)); if (nxt_slow_path(listen_sockets == NULL)) { diff --git a/test/unit.py b/test/unit.py index cec62489..98a0a4db 100644 --- a/test/unit.py +++ b/test/unit.py @@ -477,7 +477,7 @@ class TestUnitApplicationGo(TestUnitApplicationProto): }, "applications": { script: { - "type": "go", + "type": "external", "processes": { "spare": 0 }, "working_directory": self.current_dir + '/go/' + script, "executable": self.testdir + '/go/' + name -- cgit From 49ec17b1ef1d35cda54dc545c1d37d02b35afdcb Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Wed, 17 Oct 2018 15:52:44 +0300 Subject: Installing libunit headers and static library. --- auto/help | 2 ++ auto/make | 26 ++++++++++++++++++++++++++ auto/options | 12 ++++++++++++ auto/summary | 2 ++ configure | 2 ++ 5 files changed, 44 insertions(+) diff --git a/auto/help b/auto/help index 4d0b84e9..91be220f 100644 --- a/auto/help +++ b/auto/help @@ -16,6 +16,8 @@ cat << END default: "$NXT_BINDIR" --sbindir=DIRECTORY set system admin executables directory name default: "$NXT_SBINDIR" + --libdir=DIRECTORY set library directory name, default: "$NXT_LIBDIR" + --incdir=DIRECTORY set includes directory name, default: "$NXT_INCDIR" --modules=DIRECTORY set modules directory name, default: "$NXT_MODULES" --state=DIRECTORY set state directory name, default: "$NXT_STATE" diff --git a/auto/make b/auto/make index bace16e9..5bbca9e4 100644 --- a/auto/make +++ b/auto/make @@ -277,6 +277,32 @@ ${NXT_DAEMON}-uninstall: END +cat << END >> $NXT_MAKEFILE + +.PHONY: libunit-install libunit-uninstall + +libunit-install: $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC + install -d \$(DESTDIR)$NXT_LIBDIR + install -p -m u=rw,go=r $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC \ + \$(DESTDIR)$NXT_LIBDIR/ + install -d \$(DESTDIR)$NXT_INCDIR + install -p -m u=rw,go=r src/nxt_unit.h src/nxt_unit_field.h \ + src/nxt_unit_request.h src/nxt_unit_response.h src/nxt_unit_sptr.h \ + src/nxt_unit_typedefs.h \$(DESTDIR)$NXT_INCDIR/ + +libunit-uninstall: + rm -f \$(DESTDIR)$NXT_LIBDIR/$NXT_LIB_UNIT_STATIC + @rmdir -p \$(DESTDIR)$NXT_LIBDIR 2>/dev/null || true + rm -f \$(DESTDIR)$NXT_INCDIR/nxt_unit.h \ + \$(DESTDIR)$NXT_INCDIR/nxt_unit_field.h \ + \$(DESTDIR)$NXT_INCDIR/nxt_unit_request.h \ + \$(DESTDIR)$NXT_INCDIR/nxt_unit_response.h \ + \$(DESTDIR)$NXT_INCDIR/nxt_unit_sptr.h \ + \$(DESTDIR)$NXT_INCDIR/nxt_unit_typedefs.h + @rmdir -p \$(DESTDIR)$NXT_INCDIR 2>/dev/null || true + +END + # Makefile. # *.dSYM is MacOSX Clang debug information. diff --git a/auto/options b/auto/options index eadfb198..0d31abad 100644 --- a/auto/options +++ b/auto/options @@ -54,6 +54,8 @@ do --prefix=*) NXT_PREFIX="$value" ;; --bindir=*) NXT_BINDIR="$value" ;; --sbindir=*) NXT_SBINDIR="$value" ;; + --libdir=*) NXT_LIBDIR="$value" ;; + --incdir=*) NXT_INCDIR="$value" ;; --modules=*) NXT_MODULES="$value" ;; --state=*) NXT_STATE="$value" ;; @@ -127,6 +129,16 @@ case "$NXT_SBINDIR" in *) NXT_SBINDIR="$NXT_PREFIX$NXT_SBINDIR" ;; esac +case "$NXT_LIBDIR" in + /*) ;; + *) NXT_LIBDIR="$NXT_PREFIX$NXT_LIBDIR" ;; +esac + +case "$NXT_INCDIR" in + /*) ;; + *) NXT_INCDIR="$NXT_PREFIX$NXT_INCDIR" ;; +esac + case "$NXT_MODULES" in /*) ;; *) NXT_MODULES="$NXT_PREFIX$NXT_MODULES" ;; diff --git a/auto/summary b/auto/summary index 695b21f7..ce6b42db 100644 --- a/auto/summary +++ b/auto/summary @@ -9,6 +9,8 @@ Configuration summary: unit bin directory: "$NXT_BINDIR" unit sbin directory: "$NXT_SBINDIR" + unit lib directory: "$NXT_LIBDIR" + unit include directory: "$NXT_INCDIR" unit modules directory: "$NXT_MODULES" unit state directory: "$NXT_STATE" diff --git a/configure b/configure index db64cb1e..13f2db6b 100755 --- a/configure +++ b/configure @@ -32,6 +32,8 @@ CC=${CC:-cc} NXT_DAEMON=unitd NXT_BINDIR="bin" NXT_SBINDIR="sbin" +NXT_LIBDIR="lib" +NXT_INCDIR="include" NXT_MODULES="modules" NXT_STATE="state" NXT_PID="unit.pid" -- cgit From 0ee8de55433725f3084a3ccd9664f1eca365e9af Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Thu, 18 Oct 2018 13:38:30 +0300 Subject: Fixed Makefile target for NodeJS. --- auto/modules/nodejs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/auto/modules/nodejs b/auto/modules/nodejs index 25e75f01..56f84876 100644 --- a/auto/modules/nodejs +++ b/auto/modules/nodejs @@ -115,7 +115,7 @@ if grep ^$NXT_NODE: $NXT_MAKEFILE 2>&1 > /dev/null; then fi NXT_NODE_TMP=${NXT_BUILD_DIR}/src/${NXT_NODE}/unit-http -NXT_NODE_TARBALL=${PWD}/${NXT_BUILD_DIR}/${NXT_NODE}-unit-http.tar.gz +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" @@ -142,13 +142,13 @@ ${NXT_NODE_TARBALL}: ${NXT_NODE}-copy ${NXT_NODE}-install: ${NXT_NODE_TARBALL} \ $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC ${NXT_NODE_EXPORTS} && \\ - ${NXT_NPM} install -g ${NXT_NODE_TARBALL} --unsafe-perm=true + ${NXT_NPM} install -g ${PWD}/${NXT_NODE_TARBALL} --unsafe-perm=true ${NXT_NODE}-local-install: ${NXT_NODE_TARBALL} \ $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC ${NXT_NODE_EXPORTS} && \\ mkdir -p \$(DESTDIR) && \\ - cd \$(DESTDIR) && ${NXT_NPM} install ${NXT_NODE_TARBALL} + cd \$(DESTDIR) && ${NXT_NPM} install ${PWD}/${NXT_NODE_TARBALL} ${NXT_NODE}-build: ${NXT_NODE} -- cgit From 3061e8333db784619d982b618c9792ec8da36e3a Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Thu, 18 Oct 2018 18:46:21 +0300 Subject: Tests: provide openssl.conf in test_tls_certificate_key_ec. Previously, test failed if openssl was unable to load config info, or the system's openssl.cnf was picked up, which is wrong as well. --- test/test_tls.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test_tls.py b/test/test_tls.py index 26bedcb7..aaf939ec 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -137,11 +137,14 @@ class TestUnitTLS(unit.TestUnitApplicationTLS): 'RSA (1024 bits)', 'certificate key rsa') def test_tls_certificate_key_ec(self): + self.load('empty') + subprocess.call(['openssl', 'ecparam', '-noout', '-genkey', '-out', self.testdir + '/ec.key', '-name', 'prime256v1']) subprocess.call(['openssl', 'req', '-x509', '-new', + '-config', self.testdir + '/openssl.conf', '-key', self.testdir + '/ec.key', '-subj', '/CN=ec/', '-out', self.testdir + '/ec.crt']) -- cgit From 161e1839a5e3d9d906c047c2464a239a632d42c2 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Mon, 22 Oct 2018 16:16:05 +0300 Subject: Compatibility with LibreSSL. LibreSSL uses high OPENSSL_VERSION_NUMBER, but has no SSL_CTX_add0_chain_cert(). --- src/nxt_openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nxt_openssl.c b/src/nxt_openssl.c index 91ba3cb0..441da54b 100644 --- a/src/nxt_openssl.c +++ b/src/nxt_openssl.c @@ -404,7 +404,7 @@ nxt_openssl_chain_file(SSL_CTX *ctx, nxt_fd_t fd) * while the main certificate needs a X509_free() call, since * its reference count is increased by SSL_CTX_use_certificate(). */ -#if OPENSSL_VERSION_NUMBER > 0x10002000L +#ifdef SSL_CTX_add0_chain_cert if (SSL_CTX_add0_chain_cert(ctx, ca) != 1) { #else if (SSL_CTX_add_extra_chain_cert(ctx, ca) != 1) { -- cgit From a4aaf906794d9f82710614ba368a36500e8a8254 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Mon, 22 Oct 2018 16:01:10 +0300 Subject: Re-engineered timers. To optimize rbtree operations, all changes are stored in array and later processed in batches. The previous implementation of this mechanics had a number of design flaws. Each change was saved in a new array entry; until the changes were applied, the timer remained in an intermediate state (NXT_TIMER_CHANGING). This intermediate state didn't allow to identify if time was going to be disabled or enabled. However, the nxt_conn_io_read() function relied on this information; as a result, in some cases the read timeout wasn't set. Also, the nxt_timer_delete() function did not reliably track whether a timer was added to the work queue. It checked the NXT_TIMER_ENQUEUED state of a timer, but this state could be reset to NXT_TIMER_DISABLED by a nxt_timer_disable() call or another nxt_timer_delete() call. Now, instead of keeping the whole history of the timer's changes, the new implementation updates the timer state immediately, and only one operation is added to the array to add or delete timer in the rbtree according to its final state. --- src/nxt_conn_read.c | 4 +- src/nxt_timer.c | 135 +++++++++++++++++++++------------------------------- src/nxt_timer.h | 36 +++++++++----- 3 files changed, 78 insertions(+), 97 deletions(-) diff --git a/src/nxt_conn_read.c b/src/nxt_conn_read.c index 21086233..e458bf81 100644 --- a/src/nxt_conn_read.c +++ b/src/nxt_conn_read.c @@ -105,7 +105,7 @@ nxt_conn_io_read(nxt_task_t *task, void *obj, void *data) * occured during read operation, it toggled write event * internally so only read timer should be set. */ - if (c->read_timer.state == NXT_TIMER_DISABLED) { + if (!c->read_timer.enabled) { nxt_conn_timer(engine, c, state, &c->read_timer); } @@ -117,7 +117,7 @@ nxt_conn_io_read(nxt_task_t *task, void *obj, void *data) nxt_fd_event_enable_read(engine, &c->socket); } - if (state->timer_autoreset || c->read_timer.state == NXT_TIMER_DISABLED) { + if (state->timer_autoreset || !c->read_timer.enabled) { nxt_conn_timer(engine, c, state, &c->read_timer); } } diff --git a/src/nxt_timer.c b/src/nxt_timer.c index f56ddeb6..97807d75 100644 --- a/src/nxt_timer.c +++ b/src/nxt_timer.c @@ -32,6 +32,10 @@ nxt_timers_init(nxt_timers_t *timers, nxt_uint_t mchanges) { nxt_rbtree_init(&timers->tree, nxt_timer_rbtree_compare); + if (mchanges > NXT_TIMER_MAX_CHANGES) { + mchanges = NXT_TIMER_MAX_CHANGES; + } + timers->mchanges = mchanges; timers->changes = nxt_malloc(sizeof(nxt_timer_change_t) * mchanges); @@ -71,66 +75,47 @@ nxt_timer_add(nxt_event_engine_t *engine, nxt_timer_t *timer, time = engine->timers.now + timeout; - if (timer->state != NXT_TIMER_CHANGING) { + nxt_debug(timer->task, "timer add: %M %M:%M", timer->time, timeout, time); - if (nxt_timer_is_in_tree(timer)) { + timer->enabled = 1; - diff = nxt_msec_diff(time, timer->time); - /* - * Use the previous timer if difference between it and the - * new timer is less than required precision milliseconds: this - * decreases number of rbtree operations for fast connections. - */ - if (nxt_abs(diff) < timer->precision) { - nxt_debug(timer->task, "timer previous: %M:%d", - time, timer->state); + if (nxt_timer_is_in_tree(timer)) { - timer->state = NXT_TIMER_WAITING; - return; - } + diff = nxt_msec_diff(time, timer->time); + /* + * Use the previous timer if difference between it and the + * new timer is less than required precision milliseconds: this + * decreases number of rbtree operations for fast connections. + */ + if (nxt_abs(diff) < timer->precision) { + nxt_debug(timer->task, "timer previous: %M", time); + + nxt_timer_change(engine, timer, NXT_TIMER_NOPE, 0); + return; } } - nxt_debug(timer->task, "timer add: %M:%d %M:%M", - timer->time, timer->state, timeout, time); - nxt_timer_change(engine, timer, NXT_TIMER_ADD, time); } -void -nxt_timer_disable(nxt_event_engine_t *engine, nxt_timer_t *timer) -{ - nxt_debug(timer->task, "timer disable: %M:%d", timer->time, timer->state); - - if (timer->state != NXT_TIMER_CHANGING) { - timer->state = NXT_TIMER_DISABLED; - - } else { - nxt_timer_change(engine, timer, NXT_TIMER_DISABLE, 0); - } -} - - nxt_bool_t nxt_timer_delete(nxt_event_engine_t *engine, nxt_timer_t *timer) { - nxt_bool_t pending; + nxt_debug(timer->task, "timer delete: %M", timer->time); + + timer->enabled = 0; - if (nxt_timer_is_in_tree(timer) || timer->state == NXT_TIMER_CHANGING) { - nxt_debug(timer->task, "timer delete: %M:%d", - timer->time, timer->state); + if (nxt_timer_is_in_tree(timer)) { nxt_timer_change(engine, timer, NXT_TIMER_DELETE, 0); return 1; } - pending = (timer->state == NXT_TIMER_ENQUEUED); - - timer->state = NXT_TIMER_DISABLED; + nxt_timer_change(engine, timer, NXT_TIMER_NOPE, 0); - return pending; + return (timer->queued || timer->change != NXT_TIMER_NO_CHANGE); } @@ -143,31 +128,35 @@ nxt_timer_change(nxt_event_engine_t *engine, nxt_timer_t *timer, timers = &engine->timers; - if (timers->nchanges >= timers->mchanges) { - nxt_timer_changes_commit(engine); + if (timer->change == NXT_TIMER_NO_CHANGE) { + + if (change == NXT_TIMER_NOPE) { + return; + } + + if (timers->nchanges >= timers->mchanges) { + nxt_timer_changes_commit(engine); + } + + timers->nchanges++; + timer->change = timers->nchanges; } nxt_debug(timer->task, "timer change: %M:%d", time, change); - timer->state = NXT_TIMER_CHANGING; - - ch = &timers->changes[timers->nchanges]; + ch = &timers->changes[timer->change - 1]; ch->change = change; ch->time = time; ch->timer = timer; - - timers->nchanges++; } static void nxt_timer_changes_commit(nxt_event_engine_t *engine) { - int32_t diff; nxt_timer_t *timer; nxt_timers_t *timers; - nxt_timer_state_t state; nxt_timer_change_t *ch, *end; timers = &engine->timers; @@ -178,28 +167,16 @@ nxt_timer_changes_commit(nxt_event_engine_t *engine) end = ch + timers->nchanges; while (ch < end) { - state = NXT_TIMER_DISABLED; - timer = ch->timer; switch (ch->change) { + case NXT_TIMER_NOPE: + break; + case NXT_TIMER_ADD: if (nxt_timer_is_in_tree(timer)) { - - diff = nxt_msec_diff(ch->time, timer->time); - /* See the comment in nxt_timer_add(). */ - - if (nxt_abs(diff) < timer->precision) { - nxt_debug(timer->task, "timer rbtree previous: %M:%d", - ch->time, timer->state); - - state = NXT_TIMER_WAITING; - break; - } - - nxt_debug(timer->task, "timer rbtree delete: %M:%d", - timer->time, timer->state); + nxt_debug(timer->task, "timer rbtree delete: %M", timer->time); nxt_rbtree_delete(&timers->tree, &timer->node); } @@ -210,26 +187,19 @@ nxt_timer_changes_commit(nxt_event_engine_t *engine) nxt_rbtree_insert(&timers->tree, &timer->node); nxt_timer_in_tree_set(timer); - state = NXT_TIMER_WAITING; break; case NXT_TIMER_DELETE: - if (nxt_timer_is_in_tree(timer)) { - nxt_debug(timer->task, "timer rbtree delete: %M:%d", - timer->time, timer->state); + nxt_debug(timer->task, "timer rbtree delete: %M", timer->time); - nxt_rbtree_delete(&timers->tree, &timer->node); - nxt_timer_in_tree_clear(timer); - } + nxt_rbtree_delete(&timers->tree, &timer->node); + nxt_timer_in_tree_clear(timer); break; - - case NXT_TIMER_DISABLE: - break; } - timer->state = state; + timer->change = NXT_TIMER_NO_CHANGE; ch++; } @@ -270,7 +240,7 @@ nxt_timer_find(nxt_event_engine_t *engine) * return much earlier and the disabled timer can be reactivated. */ - if (timer->state != NXT_TIMER_DISABLED) { + if (timer->enabled) { time = timer->time; timers->minimum = time; @@ -324,14 +294,13 @@ nxt_timer_expire(nxt_event_engine_t *engine, nxt_msec_t now) next = nxt_rbtree_node_successor(tree, node); - nxt_debug(timer->task, "timer expire delete: %M:%d", - timer->time, timer->state); + nxt_debug(timer->task, "timer expire delete: %M", timer->time); nxt_rbtree_delete(tree, &timer->node); nxt_timer_in_tree_clear(timer); - if (timer->state != NXT_TIMER_DISABLED) { - timer->state = NXT_TIMER_ENQUEUED; + if (timer->enabled) { + timer->queued = 1; nxt_work_queue_add(timer->work_queue, nxt_timer_handler, timer->task, timer, NULL); @@ -347,8 +316,10 @@ nxt_timer_handler(nxt_task_t *task, void *obj, void *data) timer = obj; - if (timer->state == NXT_TIMER_ENQUEUED) { - timer->state = NXT_TIMER_DISABLED; + timer->queued = 0; + + if (timer->enabled && timer->change == NXT_TIMER_NO_CHANGE) { + timer->enabled = 0; timer->handler(task, timer, NULL); } diff --git a/src/nxt_timer.h b/src/nxt_timer.h index 6531657d..211564d6 100644 --- a/src/nxt_timer.h +++ b/src/nxt_timer.h @@ -13,20 +13,24 @@ //#define NXT_TIMER_DEFAULT_PRECISION 1 -typedef enum { - NXT_TIMER_DISABLED = 0, - NXT_TIMER_CHANGING, - NXT_TIMER_WAITING, - NXT_TIMER_ENQUEUED, -} nxt_timer_state_t; +/* + * The nxt_timer_t structure can hold up to 14 bits of change index, + * but 0 reserved for NXT_TIMER_NO_CHANGE. + */ +#define NXT_TIMER_MAX_CHANGES 16383 +#define NXT_TIMER_NO_CHANGE 0 typedef struct { /* The rbtree node must be the first field. */ NXT_RBTREE_NODE (node); - nxt_timer_state_t state:8; uint8_t precision; + + uint16_t change:14; + uint16_t enabled:1; + uint16_t queued:1; + nxt_msec_t time; nxt_work_queue_t *work_queue; @@ -37,13 +41,13 @@ typedef struct { } nxt_timer_t; -#define NXT_TIMER { NXT_RBTREE_NODE_INIT, NXT_TIMER_DISABLED, \ - 0, 0, NULL, NULL, NULL, NULL } +#define NXT_TIMER { NXT_RBTREE_NODE_INIT, 0, NXT_TIMER_NO_CHANGE, \ + 0, 0, 0, NULL, NULL, NULL, NULL } typedef enum { - NXT_TIMER_ADD = 0, - NXT_TIMER_DISABLE, + NXT_TIMER_NOPE = 0, + NXT_TIMER_ADD, NXT_TIMER_DELETE, } nxt_timer_operation_t; @@ -94,10 +98,16 @@ void nxt_timer_expire(nxt_event_engine_t *engine, nxt_msec_t now); NXT_EXPORT void nxt_timer_add(nxt_event_engine_t *engine, nxt_timer_t *timer, nxt_msec_t timeout); -NXT_EXPORT void nxt_timer_disable(nxt_event_engine_t *engine, - nxt_timer_t *timer); NXT_EXPORT nxt_bool_t nxt_timer_delete(nxt_event_engine_t *engine, nxt_timer_t *timer); +nxt_inline void +nxt_timer_disable(nxt_event_engine_t *engine, nxt_timer_t *timer) +{ + nxt_debug(timer->task, "timer disable: %M", timer->time); + + timer->enabled = 0; +} + #endif /* _NXT_TIMER_H_INCLUDED_ */ -- cgit From b20e995e80d236945ec8388dfee37257ce9e5445 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Mon, 22 Oct 2018 16:02:14 +0300 Subject: Timers: separation of delete and insert operations on rbtree. Delete/insert operation complexity for a red-black tree is O(log n), where n is the total number of tree elements. If all delete operations are performed before all insert operations, the average number of tree elements during an operation will be lower than in the mixed-operations case. --- src/nxt_timer.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/nxt_timer.c b/src/nxt_timer.c index 97807d75..0b89dafc 100644 --- a/src/nxt_timer.c +++ b/src/nxt_timer.c @@ -155,7 +155,7 @@ nxt_timer_change(nxt_event_engine_t *engine, nxt_timer_t *timer, static void nxt_timer_changes_commit(nxt_event_engine_t *engine) { - nxt_timer_t *timer; + nxt_timer_t *timer, **add, **add_end; nxt_timers_t *timers; nxt_timer_change_t *ch, *end; @@ -166,6 +166,9 @@ nxt_timer_changes_commit(nxt_event_engine_t *engine) ch = timers->changes; end = ch + timers->nchanges; + add = (nxt_timer_t **) ch; + add_end = add; + while (ch < end) { timer = ch->timer; @@ -175,20 +178,16 @@ nxt_timer_changes_commit(nxt_event_engine_t *engine) break; case NXT_TIMER_ADD: - if (nxt_timer_is_in_tree(timer)) { - nxt_debug(timer->task, "timer rbtree delete: %M", timer->time); - - nxt_rbtree_delete(&timers->tree, &timer->node); - } timer->time = ch->time; - nxt_debug(timer->task, "timer rbtree insert: %M", timer->time); + *add_end++ = timer; - nxt_rbtree_insert(&timers->tree, &timer->node); - nxt_timer_in_tree_set(timer); + if (!nxt_timer_is_in_tree(timer)) { + break; + } - break; + /* Fall through. */ case NXT_TIMER_DELETE: nxt_debug(timer->task, "timer rbtree delete: %M", timer->time); @@ -204,6 +203,17 @@ nxt_timer_changes_commit(nxt_event_engine_t *engine) ch++; } + while (add < add_end) { + timer = *add; + + nxt_debug(timer->task, "timer rbtree insert: %M", timer->time); + + nxt_rbtree_insert(&timers->tree, &timer->node); + nxt_timer_in_tree_set(timer); + + add++; + } + timers->nchanges = 0; } -- cgit From da0ef366dc1affa740618eb4f4baa8bbb62f8d70 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Mon, 22 Oct 2018 16:04:16 +0300 Subject: Handling of timers with bias. Timers that don't require maximum precision (most of them, actually) can be triggered earlier or later within the bias interval. To reduce wakeups by timers, the expire function now triggers not only all timers that fall within the elapsed time, but also those whose bias falls within this interval. --- src/nxt_conn.h | 2 +- src/nxt_http_request.c | 2 +- src/nxt_router.c | 4 ++-- src/nxt_timer.c | 37 ++++++++++++++++++++++--------------- src/nxt_timer.h | 8 ++++---- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/nxt_conn.h b/src/nxt_conn.h index 6f6cae9c..d8b48694 100644 --- a/src/nxt_conn.h +++ b/src/nxt_conn.h @@ -175,7 +175,7 @@ struct nxt_conn_s { do { \ (ev)->work_queue = (wq); \ (ev)->log = &(c)->log; \ - (ev)->precision = NXT_TIMER_DEFAULT_PRECISION; \ + (ev)->bias = NXT_TIMER_DEFAULT_BIAS; \ } while (0) diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 06d45247..b80998cb 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -192,7 +192,7 @@ nxt_http_app_request(nxt_task_t *task, void *obj, void *data) ar->timer.task = &engine->task; ar->timer.work_queue = &engine->fast_work_queue; ar->timer.log = engine->task.log; - ar->timer.precision = NXT_TIMER_DEFAULT_PRECISION; + ar->timer.bias = NXT_TIMER_DEFAULT_BIAS; ar->r.remote.start = nxt_sockaddr_address(r->remote); ar->r.remote.length = r->remote->address_length; diff --git a/src/nxt_router.c b/src/nxt_router.c index 3a5382e4..7ecbca81 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -1578,7 +1578,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, app_joint->use_count = 1; app_joint->app = app; - app_joint->idle_timer.precision = NXT_TIMER_DEFAULT_PRECISION; + app_joint->idle_timer.bias = NXT_TIMER_DEFAULT_BIAS; app_joint->idle_timer.work_queue = &engine->fast_work_queue; app_joint->idle_timer.handler = nxt_router_app_idle_timeout; app_joint->idle_timer.task = &engine->task; @@ -4119,7 +4119,7 @@ nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, void *data) nxt_assert(app->engine == engine); - threshold = engine->timers.now + app->joint->idle_timer.precision; + threshold = engine->timers.now + app->joint->idle_timer.bias; timeout = 0; nxt_thread_mutex_lock(&app->mutex); diff --git a/src/nxt_timer.c b/src/nxt_timer.c index 0b89dafc..cba4755b 100644 --- a/src/nxt_timer.c +++ b/src/nxt_timer.c @@ -75,7 +75,8 @@ nxt_timer_add(nxt_event_engine_t *engine, nxt_timer_t *timer, time = engine->timers.now + timeout; - nxt_debug(timer->task, "timer add: %M %M:%M", timer->time, timeout, time); + nxt_debug(timer->task, "timer add: %M±%d %M:%M", + timer->time, timer->bias, timeout, time); timer->enabled = 1; @@ -84,11 +85,12 @@ nxt_timer_add(nxt_event_engine_t *engine, nxt_timer_t *timer, diff = nxt_msec_diff(time, timer->time); /* * Use the previous timer if difference between it and the - * new timer is less than required precision milliseconds: this - * decreases number of rbtree operations for fast connections. + * new timer is within bias: this decreases number of rbtree + * operations for fast connections. */ - if (nxt_abs(diff) < timer->precision) { - nxt_debug(timer->task, "timer previous: %M", time); + if (nxt_abs(diff) <= timer->bias) { + nxt_debug(timer->task, "timer previous: %M±%d", + time, timer->bias); nxt_timer_change(engine, timer, NXT_TIMER_NOPE, 0); return; @@ -102,7 +104,8 @@ nxt_timer_add(nxt_event_engine_t *engine, nxt_timer_t *timer, nxt_bool_t nxt_timer_delete(nxt_event_engine_t *engine, nxt_timer_t *timer) { - nxt_debug(timer->task, "timer delete: %M", timer->time); + nxt_debug(timer->task, "timer delete: %M±%d", + timer->time, timer->bias); timer->enabled = 0; @@ -142,7 +145,8 @@ nxt_timer_change(nxt_event_engine_t *engine, nxt_timer_t *timer, timer->change = timers->nchanges; } - nxt_debug(timer->task, "timer change: %M:%d", time, change); + nxt_debug(timer->task, "timer change: %M±%d:%d", + time, timer->bias, change); ch = &timers->changes[timer->change - 1]; @@ -190,7 +194,8 @@ nxt_timer_changes_commit(nxt_event_engine_t *engine) /* Fall through. */ case NXT_TIMER_DELETE: - nxt_debug(timer->task, "timer rbtree delete: %M", timer->time); + nxt_debug(timer->task, "timer rbtree delete: %M±%d", + timer->time, timer->bias); nxt_rbtree_delete(&timers->tree, &timer->node); nxt_timer_in_tree_clear(timer); @@ -206,7 +211,8 @@ nxt_timer_changes_commit(nxt_event_engine_t *engine) while (add < add_end) { timer = *add; - nxt_debug(timer->task, "timer rbtree insert: %M", timer->time); + nxt_debug(timer->task, "timer rbtree insert: %M±%d", + timer->time, timer->bias); nxt_rbtree_insert(&timers->tree, &timer->node); nxt_timer_in_tree_set(timer); @@ -252,10 +258,10 @@ nxt_timer_find(nxt_event_engine_t *engine) if (timer->enabled) { time = timer->time; - timers->minimum = time; + timers->minimum = time - timer->bias; - nxt_debug(timer->task, "timer found minimum: %M:%M", - time, timers->now); + nxt_debug(timer->task, "timer found minimum: %M±%d:%M", + time, timer->bias, timers->now); delta = nxt_msec_diff(time, timers->now); @@ -297,14 +303,15 @@ nxt_timer_expire(nxt_event_engine_t *engine, nxt_msec_t now) { timer = (nxt_timer_t *) node; - /* timer->time > now */ - if (nxt_msec_diff(timer->time , now) > 0) { + /* timer->time > now + timer->bias */ + if (nxt_msec_diff(timer->time , now) > (int32_t) timer->bias) { return; } next = nxt_rbtree_node_successor(tree, node); - nxt_debug(timer->task, "timer expire delete: %M", timer->time); + nxt_debug(timer->task, "timer expire delete: %M±%d", + timer->time, timer->bias); nxt_rbtree_delete(tree, &timer->node); nxt_timer_in_tree_clear(timer); diff --git a/src/nxt_timer.h b/src/nxt_timer.h index 211564d6..4199f0dd 100644 --- a/src/nxt_timer.h +++ b/src/nxt_timer.h @@ -8,9 +8,9 @@ #define _NXT_TIMER_H_INCLUDED_ -/* Valid values are between 1ms to 255ms. */ -#define NXT_TIMER_DEFAULT_PRECISION 100 -//#define NXT_TIMER_DEFAULT_PRECISION 1 +/* Valid values are between 0ms to 255ms. */ +#define NXT_TIMER_DEFAULT_BIAS 50 +//#define NXT_TIMER_DEFAULT_BIAS 0 /* @@ -25,7 +25,7 @@ typedef struct { /* The rbtree node must be the first field. */ NXT_RBTREE_NODE (node); - uint8_t precision; + uint8_t bias; uint16_t change:14; uint16_t enabled:1; -- cgit From deeb276d2386b90e695fc0650bfb7e08806264ee Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Mon, 22 Oct 2018 16:25:58 +0300 Subject: Removed duplicate code in epoll. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is related to #173 issue on GitHub. Thanks to 洪志道 (Hong Zhi Dao). --- src/nxt_epoll_engine.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/nxt_epoll_engine.c b/src/nxt_epoll_engine.c index 68e8d609..bc606d7a 100644 --- a/src/nxt_epoll_engine.c +++ b/src/nxt_epoll_engine.c @@ -942,8 +942,6 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) ev->read = NXT_EVENT_DISABLED; } - error = 0; - nxt_work_queue_add(ev->read_work_queue, ev->read_handler, ev->task, ev, ev->data); @@ -962,8 +960,6 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) ev->write = NXT_EVENT_DISABLED; } - error = 0; - nxt_work_queue_add(ev->write_work_queue, ev->write_handler, ev->task, ev, ev->data); @@ -972,11 +968,6 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) nxt_epoll_disable_write(engine, ev); } } - - if (error) { - ev->read_ready = 1; - ev->write_ready = 1; - } } } -- cgit From 50dd54877dc88ade87f4259a74918ddfa4498880 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Mon, 22 Oct 2018 17:43:28 +0300 Subject: Improved epoll failures handling. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit epoll changes are committed to the kernel before epoll_wait() or on changes array overflow. In the latter case if there are errors epoll_wait() timeout was not set to zero. This commit is related to #173 issue on GitHub. Thanks to 洪志道 (Hong Zhi Dao). --- src/nxt_epoll_engine.c | 23 +++++++++++------------ src/nxt_event_engine.h | 2 ++ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/nxt_epoll_engine.c b/src/nxt_epoll_engine.c index bc606d7a..d87b92cf 100644 --- a/src/nxt_epoll_engine.c +++ b/src/nxt_epoll_engine.c @@ -67,7 +67,7 @@ static void nxt_epoll_enable_accept(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static void nxt_epoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, int op, uint32_t events); -static nxt_int_t nxt_epoll_commit_changes(nxt_event_engine_t *engine); +static void nxt_epoll_commit_changes(nxt_event_engine_t *engine); static void nxt_epoll_error_handler(nxt_task_t *task, void *obj, void *data); #if (NXT_HAVE_SIGNALFD) static nxt_int_t nxt_epoll_add_signal(nxt_event_engine_t *engine); @@ -593,7 +593,7 @@ nxt_epoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, int op, engine->u.epoll.fd, ev->fd, op, events); if (engine->u.epoll.nchanges >= engine->u.epoll.mchanges) { - (void) nxt_epoll_commit_changes(engine); + nxt_epoll_commit_changes(engine); } ev->changing = 1; @@ -605,18 +605,16 @@ nxt_epoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, int op, } -static nxt_int_t +static void nxt_epoll_commit_changes(nxt_event_engine_t *engine) { int ret; - nxt_int_t retval; nxt_fd_event_t *ev; nxt_epoll_change_t *change, *end; nxt_debug(&engine->task, "epoll %d changes:%ui", engine->u.epoll.fd, engine->u.epoll.nchanges); - retval = NXT_OK; change = engine->u.epoll.changes; end = change + engine->u.epoll.nchanges; @@ -637,7 +635,7 @@ nxt_epoll_commit_changes(nxt_event_engine_t *engine) nxt_work_queue_add(&engine->fast_work_queue, nxt_epoll_error_handler, ev->task, ev, ev->data); - retval = NXT_ERROR; + engine->u.epoll.error = 1; } change++; @@ -645,8 +643,6 @@ nxt_epoll_commit_changes(nxt_event_engine_t *engine) } while (change < end); engine->u.epoll.nchanges = 0; - - return retval; } @@ -884,10 +880,13 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) struct epoll_event *event; if (engine->u.epoll.nchanges != 0) { - if (nxt_epoll_commit_changes(engine) != NXT_OK) { - /* Error handlers have been enqueued on failure. */ - timeout = 0; - } + nxt_epoll_commit_changes(engine); + } + + if (engine->u.epoll.error) { + engine->u.epoll.error = 0; + /* Error handlers have been enqueued on failure. */ + timeout = 0; } nxt_debug(&engine->task, "epoll_wait(%d) timeout:%M", diff --git a/src/nxt_event_engine.h b/src/nxt_event_engine.h index 7a7149e6..365d9e89 100644 --- a/src/nxt_event_engine.h +++ b/src/nxt_event_engine.h @@ -202,6 +202,8 @@ typedef struct { nxt_uint_t mchanges; int mevents; + uint8_t error; /* 1 bit */ + nxt_epoll_change_t *changes; struct epoll_event *events; -- cgit From 57991dc3f2ee1a028605e5dde01cac367e09142c Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Mon, 22 Oct 2018 17:43:31 +0300 Subject: Fixed termination signal handlers in worker processes. This closes #99 issue on GitHub. Thanks to Julian Brost. --- src/nxt_worker_process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nxt_worker_process.c b/src/nxt_worker_process.c index 8bcfb467..c068cca4 100644 --- a/src/nxt_worker_process.c +++ b/src/nxt_worker_process.c @@ -42,8 +42,8 @@ nxt_port_handlers_t nxt_discovery_process_port_handlers = { const nxt_sig_event_t nxt_worker_process_signals[] = { nxt_event_signal(SIGHUP, nxt_worker_process_signal_handler), nxt_event_signal(SIGINT, nxt_worker_process_sigterm_handler), - nxt_event_signal(SIGQUIT, nxt_worker_process_sigterm_handler), - nxt_event_signal(SIGTERM, nxt_worker_process_sigquit_handler), + nxt_event_signal(SIGQUIT, nxt_worker_process_sigquit_handler), + nxt_event_signal(SIGTERM, nxt_worker_process_sigterm_handler), nxt_event_signal(SIGCHLD, nxt_worker_process_signal_handler), nxt_event_signal(SIGUSR1, nxt_worker_process_signal_handler), nxt_event_signal(SIGUSR2, nxt_worker_process_signal_handler), -- cgit From 0e76769c1be43fed1ad1ce32c90ca56b84af903a Mon Sep 17 00:00:00 2001 From: Andrei Belov Date: Tue, 23 Oct 2018 10:30:28 +0300 Subject: Packages: introduced unit-dev/unit-devel package. --- pkg/deb/debian/control | 8 ++++++++ pkg/deb/debian/rules.in | 8 ++++++++ pkg/rpm/unit.spec.in | 20 +++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/pkg/deb/debian/control b/pkg/deb/debian/control index e1b1bde8..c0873a1c 100644 --- a/pkg/deb/debian/control +++ b/pkg/deb/debian/control @@ -29,3 +29,11 @@ Depends: unit (= ${binary:Version}), ${misc:Depends} Description: NGINX Unit (debug symbols) This package contains the debugging symbols for NGINX Unit. + +Package: unit-dev +Section: libdevel +Priority: optional +Architecture: any +Depends: ${misc:Depends} +Description: NGINX Unit (development files) + Library and include files required for NGINX Unit modules development. diff --git a/pkg/deb/debian/rules.in b/pkg/deb/debian/rules.in index a9f68189..7eab391d 100644 --- a/pkg/deb/debian/rules.in +++ b/pkg/deb/debian/rules.in @@ -9,9 +9,12 @@ export DEB_LDFLAGS_MAINT_APPEND=-Wl,--as-needed -pie DPKG_EXPORT_BUILDFLAGS = 1 include /usr/share/dpkg/buildflags.mk +DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) + BUILDDIR_unit = $(CURDIR)/debian/build-unit BUILDDIR_unit_debug = $(CURDIR)/debian/build-unit-debug INSTALLDIR = $(CURDIR)/debian/unit +INSTALLDIR_dev = $(CURDIR)/debian/unit-dev BASEDIR = $(CURDIR) DOTESTS = 0 @@ -30,6 +33,7 @@ configure.unit: config.env.unit CFLAGS= ./configure \ %%CONFIGURE_ARGS%% \ --modules=/usr/lib/unit/modules \ + --libdir=/usr/lib/$(DEB_HOST_MULTIARCH) \ --cc-opt="$(CFLAGS)" \ --ld-opt="$(LDFLAGS)" touch $@ @@ -39,6 +43,7 @@ configure.unit_debug: config.env.unit_debug CFLAGS= ./configure \ %%CONFIGURE_ARGS%% \ --modules=/usr/lib/unit/debug-modules \ + --libdir=/usr/lib/$(DEB_HOST_MULTIARCH) \ --cc-opt="$(CFLAGS)" \ --ld-opt="$(LDFLAGS)" \ --debug @@ -47,6 +52,7 @@ configure.unit_debug: config.env.unit_debug build-arch.%: configure.% dh_testdir $(MAKE) -C $(BUILDDIR_$*) + $(MAKE) -C $(BUILDDIR_$*) build/libunit.a ifeq ($(DOTESTS), 1) $(MAKE) -C $(BUILDDIR_$*) tests endif @@ -86,7 +92,9 @@ install: build do.tests dh_installinit dh_installlogrotate cd $(BUILDDIR_unit) && DESTDIR=$(INSTALLDIR) make install + cd $(BUILDDIR_unit) && DESTDIR=$(INSTALLDIR_dev) make libunit-install install -m 755 $(BUILDDIR_unit_debug)/build/unitd $(INSTALLDIR)/usr/sbin/unitd-debug + install -m 644 $(BUILDDIR_unit_debug)/build/libunit.a $(INSTALLDIR_dev)/usr/lib/$(DEB_HOST_MULTIARCH)/libunit-debug.a mkdir -p $(INSTALLDIR)/usr/share/doc/unit/examples install -m 644 debian/unit.example.config $(INSTALLDIR)/usr/share/doc/unit/examples/example.config install -m 644 CHANGES $(INSTALLDIR)/usr/share/doc/unit/ diff --git a/pkg/rpm/unit.spec.in b/pkg/rpm/unit.spec.in index cdecaeac..e3523cb3 100644 --- a/pkg/rpm/unit.spec.in +++ b/pkg/rpm/unit.spec.in @@ -60,6 +60,14 @@ dynamically via an API. %debug_package %endif +%package devel +Summary: NGINX Unit (development files) +Version: %%VERSION%% +Release: %%RELEASE%%%{?dist}.ngx +Group: Development/Libraries +%description devel +Library and include files required for NGINX Unit modules development. + %prep %setup -q @@ -67,14 +75,17 @@ dynamically via an API. ./configure \ %{CONFIGURE_ARGS} \ --modules=%{_libdir}/unit/debug-modules \ + --libdir=%{_libdir} \ --cc-opt="%{CC_OPT}" \ --ld-opt="%{LD_OPT}" \ --debug %{__make} %{?_smp_mflags} +%{__make} %{?_smp_mflags} build/libunit.a %{__mv} build build-debug ./configure \ %{CONFIGURE_ARGS} \ --modules=%{_libdir}/unit/modules \ + --libdir=%{_libdir} \ --cc-opt="%{CC_OPT}" \ --ld-opt="%{LD_OPT}" %{__make} %{?_smp_mflags} @@ -83,9 +94,11 @@ dynamically via an API. %install %{__rm} -rf %{buildroot} %{__ln_s} build-nodebug build -DESTDIR=%{buildroot} make unitd-install +DESTDIR=%{buildroot} make unitd-install libunit-install %{__install} -m755 %{bdir}/build-debug/unitd \ %{buildroot}%{_sbindir}/unitd-debug +%{__install} -m644 %{bdir}/build-debug/libunit.a \ + %{buildroot}%{_libdir}/libunit-debug.a %{__mkdir} -p %{buildroot}%{_libdir}/unit/modules %{__mkdir} -p %{buildroot}%{_libdir}/unit/debug-modules %{__mkdir} -p %{buildroot}%{_sharedstatedir}/unit @@ -184,4 +197,9 @@ fi %dir %{_libdir}/unit/debug-modules %dir %{_sharedstatedir}/unit +%files devel +%{_libdir}/libunit.a +%{_libdir}/libunit-debug.a +%{_includedir}/nxt_*.h + %changelog -- cgit From 780181412623c0dc9232fc7f56055b6e3312a319 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Tue, 23 Oct 2018 13:06:44 +0300 Subject: Added ability to publish Node.js module. --- pkg/Makefile | 8 ++++++-- pkg/npm/Makefile | 27 +++++++++++++++++++++++++++ src/nodejs/unit-http/README.md | 19 +++++++++++++++++++ src/nodejs/unit-http/binding_pub.gyp | 2 +- src/nodejs/unit-http/package.json | 2 +- 5 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 pkg/npm/Makefile diff --git a/pkg/Makefile b/pkg/Makefile index f5cfd3c2..6001a034 100644 --- a/pkg/Makefile +++ b/pkg/Makefile @@ -6,7 +6,7 @@ VERSION ?= $(shell grep 'define NXT_VERSION' ../src/nxt_main.h \ RELEASE ?= 1 default: - @echo "available targets: dist rpm deb docker" + @echo "available targets: dist rpm deb docker npm" dist: rm -f unit-$(VERSION).tar.gz @@ -24,9 +24,13 @@ deb: docker: @cd docker && VERSION=$(VERSION) RELEASE=$(RELEASE) make all +npm: + @cd npm && VERSION=$(VERSION) RELEASE=$(RELEASE) make all + clean: @cd rpm && make clean @cd deb && make clean @cd docker && make clean + @cd npm && make clean -.PHONY: default rpm deb docker clean +.PHONY: default rpm deb docker npm clean diff --git a/pkg/npm/Makefile b/pkg/npm/Makefile new file mode 100644 index 00000000..2696c226 --- /dev/null +++ b/pkg/npm/Makefile @@ -0,0 +1,27 @@ +#!/usr/bin/make + +DEFAULT_VERSION := $(shell grep 'define NXT_VERSION' ../../src/nxt_main.h \ + | sed -e 's/^.*"\(.*\)".*/\1/') + +VERSION ?= $(DEFAULT_VERSION) +NPM ?= npm + +default: + @echo "valid targets: all publish clean" + +copy: + cp -rp ../../src/nodejs/unit-http . + mv unit-http/binding_pub.gyp unit-http/binding.gyp + sed -e 's/"version"\s*:.*/"version": "${VERSION}.0",/' \ + unit-http/package.json > unit-http/package.json.tmp + mv unit-http/package.json.tmp unit-http/package.json + +publish: copy + cd unit-http && $(NPM) publish + +all: copy + +clean: + rm -rf unit-http + +.PHONY: default all copy publish clean diff --git a/src/nodejs/unit-http/README.md b/src/nodejs/unit-http/README.md index 139597f9..71a4067a 100644 --- a/src/nodejs/unit-http/README.md +++ b/src/nodejs/unit-http/README.md @@ -1,2 +1,21 @@ +# 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 diff --git a/src/nodejs/unit-http/binding_pub.gyp b/src/nodejs/unit-http/binding_pub.gyp index e53538d0..6fe3d9bc 100644 --- a/src/nodejs/unit-http/binding_pub.gyp +++ b/src/nodejs/unit-http/binding_pub.gyp @@ -2,6 +2,6 @@ 'targets': [{ 'target_name': "unit-http", 'sources': ["unit.cpp", "addon.cpp"], - 'libraries': ["unit"] + 'libraries': ["-lunit"] }] } diff --git a/src/nodejs/unit-http/package.json b/src/nodejs/unit-http/package.json index bc481bc9..3a15d573 100644 --- a/src/nodejs/unit-http/package.json +++ b/src/nodejs/unit-http/package.json @@ -21,7 +21,7 @@ "install": "node-gyp configure build" }, "author": "Alexander Borisov", - "license": "Apache 2.0", + "license": "Apache-2.0", "gypfile": true, "dependencies": { "node-addon-api": "1.2.0" -- cgit From d4a99aad84e1ab432733650e9753814311e04a01 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Tue, 23 Oct 2018 16:31:42 +0300 Subject: Backout of ba94959b1dec and improving epoll error handling. --- src/nxt_epoll_engine.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/nxt_epoll_engine.c b/src/nxt_epoll_engine.c index d87b92cf..9f9c8f62 100644 --- a/src/nxt_epoll_engine.c +++ b/src/nxt_epoll_engine.c @@ -920,8 +920,8 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) ev->fd, events, ev, ev->read, ev->write); /* - * On error epoll may set EPOLLERR and EPOLLHUP only without EPOLLIN or - * EPOLLOUT, so the "error" variable enqueues only one active handler. + * On error epoll may set EPOLLERR and EPOLLHUP only without EPOLLIN + * or EPOLLOUT, so the "error" variable enqueues only error handler. */ error = ((events & (EPOLLERR | EPOLLHUP)) != 0); ev->epoll_error = error; @@ -932,7 +932,7 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) #endif - if ((events & EPOLLIN) || error) { + if ((events & EPOLLIN) != 0) { ev->read_ready = 1; if (ev->read != NXT_EVENT_BLOCKED) { @@ -948,9 +948,11 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) /* Level-triggered mode. */ nxt_epoll_disable_read(engine, ev); } + + error = 0; } - if ((events & EPOLLOUT) || error) { + if ((events & EPOLLOUT) != 0) { ev->write_ready = 1; if (ev->write != NXT_EVENT_BLOCKED) { @@ -966,7 +968,29 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) /* Level-triggered mode. */ nxt_epoll_disable_write(engine, ev); } + + error = 0; + } + + if (!error) { + continue; + } + + ev->read_ready = 1; + ev->write_ready = 1; + + if (ev->read == NXT_EVENT_BLOCKED && ev->write == NXT_EVENT_BLOCKED) { + + if (engine->u.epoll.mode == 0) { + /* Level-triggered mode. */ + nxt_epoll_disable(engine, ev); + } + + continue; } + + nxt_work_queue_add(&engine->fast_work_queue, nxt_epoll_error_handler, + ev->task, ev, ev->data); } } -- cgit From 6cc4080af23d0d8c39ba43f6c90de4f76d64e0f1 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Tue, 23 Oct 2018 18:55:16 +0300 Subject: Removed unused "--upstream" command line option. --- auto/sources | 2 +- src/nxt_runtime.c | 14 -------------- src/nxt_runtime.h | 1 - 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/auto/sources b/auto/sources index 0ebdab63..bc979fe2 100644 --- a/auto/sources +++ b/auto/sources @@ -74,7 +74,6 @@ NXT_LIB_SRCS=" \ src/nxt_runtime.c \ src/nxt_conf.c \ src/nxt_conf_validation.c \ - src/nxt_stream_module.c \ src/nxt_main_process.c \ src/nxt_worker_process.c \ src/nxt_controller.c \ @@ -91,6 +90,7 @@ NXT_LIB_SRCS=" \ NXT_LIB_SRC0=" \ src/nxt_buf_filter.c \ src/nxt_job_file.c \ + src/nxt_stream_module.c \ src/nxt_stream_source.c \ src/nxt_upstream_source.c \ src/nxt_http_source.c \ diff --git a/src/nxt_runtime.c b/src/nxt_runtime.c index 8f20e0a0..547c7494 100644 --- a/src/nxt_runtime.c +++ b/src/nxt_runtime.c @@ -872,20 +872,6 @@ nxt_runtime_conf_read_cmd(nxt_task_t *task, nxt_runtime_t *rt) continue; } - if (nxt_strcmp(p, "--upstream") == 0) { - if (*argv == NULL) { - nxt_alert(task, "no argument for option \"--upstream\""); - return NXT_ERROR; - } - - p = *argv++; - - rt->upstream.length = nxt_strlen(p); - rt->upstream.start = (u_char *) p; - - continue; - } - if (nxt_strcmp(p, "--user") == 0) { if (*argv == NULL) { write(STDERR_FILENO, no_user, nxt_length(no_user)); diff --git a/src/nxt_runtime.h b/src/nxt_runtime.h index e4c9e2a1..496ae478 100644 --- a/src/nxt_runtime.h +++ b/src/nxt_runtime.h @@ -74,7 +74,6 @@ struct nxt_runtime_s { nxt_sockaddr_t *controller_listen; nxt_listen_socket_t *controller_socket; - nxt_str_t upstream; }; -- cgit From 5b3d3e0a885614cbc7966bc1d4b73ba630caf1ed Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Wed, 24 Oct 2018 16:21:53 +0300 Subject: Node.js: additional type check for response.setHeader value. --- src/nodejs/unit-http/http_server.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/nodejs/unit-http/http_server.js b/src/nodejs/unit-http/http_server.js index 8c144cbe..fa7b8e9b 100755 --- a/src/nodejs/unit-http/http_server.js +++ b/src/nodejs/unit-http/http_server.js @@ -52,7 +52,7 @@ ServerResponse.prototype.setHeader = function setHeader(key, value) { throw new TypeError('Key argument must be a string'); } - let header_key_len = Buffer.byteLength(key + "", 'latin1'); + let header_key_len = Buffer.byteLength(key, 'latin1'); let header_len = 0 let header_count = 0; @@ -60,16 +60,16 @@ ServerResponse.prototype.setHeader = function setHeader(key, value) { header_count = value.length; value.forEach(function(val) { - if (typeof val !== 'string') { - throw new TypeError('Entry in arrey should be a string'); + if (typeof val !== 'string' && typeof val !== 'number') { + throw new TypeError('Array entries must be string or number'); } header_len += Buffer.byteLength(val + "", 'latin1'); }); } else { - if (typeof value !== 'string') { - throw new TypeError('Value argument must be a string or array'); + if (typeof value !== 'string' && typeof value !== 'number') { + throw new TypeError('Value argument must be string, number, or array'); } header_count = 1; @@ -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; }; -- cgit From a04554118c34448490fa6df8c7aa1791f6f471e0 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Thu, 25 Oct 2018 17:48:56 +0300 Subject: Added version 1.5 CHANGES. --- CHANGES | 24 ++++++++++++++++++++++++ docs/changes.xml | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/CHANGES b/CHANGES index 50b9a026..b1047284 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,28 @@ +Changes with Unit 1.5 25 Oct 2018 + + *) Change: the "type" of application object for Go was changed to + "external". + + *) Feature: initial version of Node.js package with basic HTTP + request-response support. + + *) Feature: compatibility with LibreSSL. + + *) Feature: --libdir and --incdir ./configure options to install libunit + headers and static library. + + *) Bugfix: connection might be closed prematurely while sending + response; the bug had appeared in 1.3. + + *) Bugfix: application processes might have stopped handling requests, + producing "last message send failed: Resource temporarily + unavailable" alerts in log; the bug had appeared in 1.4. + + *) Bugfix: Go applications didn't work when Unit was built with musl C + library. + + Changes with Unit 1.4 20 Sep 2018 *) Change: the control API maps the configuration object only at diff --git a/docs/changes.xml b/docs/changes.xml index fae63a2a..61306254 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -5,6 +5,59 @@ + + + + +the "type" of application object for Go was changed to "external". + + + + + +initial version of Node.js package with basic HTTP request-response support. + + + + + +compatibility with LibreSSL. + + + + + +--libdir and --incdir ./configure options to install libunit headers +and static library. + + + + + +connection might be closed prematurely while sending response; +the bug had appeared in 1.3. + + + + + +application processes might have stopped handling requests, producing +"last message send failed: Resource temporarily unavailable" alerts in log; +the bug had appeared in 1.4. + + + + + +Go applications didn't work when Unit was built with musl C library. + + + + + + + + + + +NGINX Unit updated to 1.5. + + + + + + diff --git a/pkg/deb/Makefile b/pkg/deb/Makefile index 6ed1c94a..735f283b 100644 --- a/pkg/deb/Makefile +++ b/pkg/deb/Makefile @@ -3,7 +3,7 @@ DEFAULT_VERSION := $(shell grep 'define NXT_VERSION' ../../src/nxt_main.h \ | sed -e 's/^.*"\(.*\)".*/\1/') -DEFAULT_RELEASE := 2 +DEFAULT_RELEASE := 1 VERSION ?= $(DEFAULT_VERSION) RELEASE ?= $(DEFAULT_RELEASE) diff --git a/pkg/deb/Makefile.go b/pkg/deb/Makefile.go index 66792a55..2d7d6537 100644 --- a/pkg/deb/Makefile.go +++ b/pkg/deb/Makefile.go @@ -4,7 +4,7 @@ MODULE_SUFFIX_go= go MODULE_SUMMARY_go= Go module for NGINX Unit MODULE_VERSION_go= $(VERSION) -MODULE_RELEASE_go= 2 +MODULE_RELEASE_go= 1 MODULE_CONFARGS_go= go --go-path=/usr/share/gocode MODULE_MAKEARGS_go= go diff --git a/pkg/deb/Makefile.go110 b/pkg/deb/Makefile.go110 index e4883af4..863f7c90 100644 --- a/pkg/deb/Makefile.go110 +++ b/pkg/deb/Makefile.go110 @@ -4,7 +4,7 @@ MODULE_SUFFIX_go110= go1.10 MODULE_SUMMARY_go110= Go 1.10 module for NGINX Unit MODULE_VERSION_go110= $(VERSION) -MODULE_RELEASE_go110= 2 +MODULE_RELEASE_go110= 1 MODULE_CONFARGS_go110= go --go=/usr/lib/go-1.10/bin/go --go-path=/usr/share/gocode MODULE_MAKEARGS_go110= /usr/lib/go-1.10/bin/go diff --git a/pkg/deb/Makefile.go17 b/pkg/deb/Makefile.go17 index 74084b49..201b32b2 100644 --- a/pkg/deb/Makefile.go17 +++ b/pkg/deb/Makefile.go17 @@ -4,7 +4,7 @@ MODULE_SUFFIX_go17= go1.7 MODULE_SUMMARY_go17= Go 1.7 module for NGINX Unit MODULE_VERSION_go17= $(VERSION) -MODULE_RELEASE_go17= 2 +MODULE_RELEASE_go17= 1 MODULE_CONFARGS_go17= go --go=/usr/lib/go-1.7/bin/go --go-path=/usr/share/gocode MODULE_MAKEARGS_go17= /usr/lib/go-1.7/bin/go diff --git a/pkg/deb/Makefile.go18 b/pkg/deb/Makefile.go18 index aaaae40d..70b155d4 100644 --- a/pkg/deb/Makefile.go18 +++ b/pkg/deb/Makefile.go18 @@ -4,7 +4,7 @@ MODULE_SUFFIX_go18= go1.8 MODULE_SUMMARY_go18= Go 1.8 module for NGINX Unit MODULE_VERSION_go18= $(VERSION) -MODULE_RELEASE_go18= 2 +MODULE_RELEASE_go18= 1 MODULE_CONFARGS_go18= go --go=/usr/lib/go-1.8/bin/go --go-path=/usr/share/gocode MODULE_MAKEARGS_go18= /usr/lib/go-1.8/bin/go diff --git a/pkg/deb/Makefile.go19 b/pkg/deb/Makefile.go19 index aef41844..9ddcc493 100644 --- a/pkg/deb/Makefile.go19 +++ b/pkg/deb/Makefile.go19 @@ -4,7 +4,7 @@ MODULE_SUFFIX_go19= go1.9 MODULE_SUMMARY_go19= Go 1.9 module for NGINX Unit MODULE_VERSION_go19= $(VERSION) -MODULE_RELEASE_go19= 2 +MODULE_RELEASE_go19= 1 MODULE_CONFARGS_go19= go --go=/usr/lib/go-1.9/bin/go --go-path=/usr/share/gocode MODULE_MAKEARGS_go19= /usr/lib/go-1.9/bin/go diff --git a/pkg/deb/Makefile.perl b/pkg/deb/Makefile.perl index 31aa976a..186b8e5a 100644 --- a/pkg/deb/Makefile.perl +++ b/pkg/deb/Makefile.perl @@ -4,7 +4,7 @@ MODULE_SUFFIX_perl= perl MODULE_SUMMARY_perl= Perl module for NGINX Unit MODULE_VERSION_perl= $(VERSION) -MODULE_RELEASE_perl= 2 +MODULE_RELEASE_perl= 1 MODULE_CONFARGS_perl= perl MODULE_MAKEARGS_perl= perl diff --git a/pkg/deb/Makefile.php b/pkg/deb/Makefile.php index 4f76e13d..193670e7 100644 --- a/pkg/deb/Makefile.php +++ b/pkg/deb/Makefile.php @@ -4,7 +4,7 @@ MODULE_SUFFIX_php= php MODULE_SUMMARY_php= PHP module for NGINX Unit MODULE_VERSION_php= $(VERSION) -MODULE_RELEASE_php= 2 +MODULE_RELEASE_php= 1 MODULE_CONFARGS_php= php MODULE_MAKEARGS_php= php diff --git a/pkg/deb/Makefile.python b/pkg/deb/Makefile.python index d4822c84..dec64b26 100644 --- a/pkg/deb/Makefile.python +++ b/pkg/deb/Makefile.python @@ -4,7 +4,7 @@ MODULE_SUFFIX_python= python MODULE_SUMMARY_python= Python module for NGINX Unit MODULE_VERSION_python= $(VERSION) -MODULE_RELEASE_python= 2 +MODULE_RELEASE_python= 1 MODULE_CONFARGS_python= python MODULE_MAKEARGS_python= python diff --git a/pkg/deb/Makefile.python27 b/pkg/deb/Makefile.python27 index d9dee872..ae1ae4c0 100644 --- a/pkg/deb/Makefile.python27 +++ b/pkg/deb/Makefile.python27 @@ -4,7 +4,7 @@ MODULE_SUFFIX_python27= python2.7 MODULE_SUMMARY_python27= Python 2.7 module for NGINX Unit MODULE_VERSION_python27= $(VERSION) -MODULE_RELEASE_python27= 2 +MODULE_RELEASE_python27= 1 MODULE_CONFARGS_python27= python --config=python2.7-config MODULE_MAKEARGS_python27= python2.7 diff --git a/pkg/deb/Makefile.python34 b/pkg/deb/Makefile.python34 index 7a9db98a..5e043ef4 100644 --- a/pkg/deb/Makefile.python34 +++ b/pkg/deb/Makefile.python34 @@ -4,7 +4,7 @@ MODULE_SUFFIX_python34= python3.4 MODULE_SUMMARY_python34= Python 3.4 module for NGINX Unit MODULE_VERSION_python34= $(VERSION) -MODULE_RELEASE_python34= 2 +MODULE_RELEASE_python34= 1 MODULE_CONFARGS_python34= python --config=python3.4-config MODULE_MAKEARGS_python34= python3.4 diff --git a/pkg/deb/Makefile.python35 b/pkg/deb/Makefile.python35 index 60256680..557690a9 100644 --- a/pkg/deb/Makefile.python35 +++ b/pkg/deb/Makefile.python35 @@ -4,7 +4,7 @@ MODULE_SUFFIX_python35= python3.5 MODULE_SUMMARY_python35= Python 3.5 module for NGINX Unit MODULE_VERSION_python35= $(VERSION) -MODULE_RELEASE_python35= 2 +MODULE_RELEASE_python35= 1 MODULE_CONFARGS_python35= python --config=python3.5-config MODULE_MAKEARGS_python35= python3.5 diff --git a/pkg/deb/Makefile.python36 b/pkg/deb/Makefile.python36 index 5f912ac1..07cbba90 100644 --- a/pkg/deb/Makefile.python36 +++ b/pkg/deb/Makefile.python36 @@ -4,7 +4,7 @@ MODULE_SUFFIX_python36= python3.6 MODULE_SUMMARY_python36= Python 3.6 module for NGINX Unit MODULE_VERSION_python36= $(VERSION) -MODULE_RELEASE_python36= 2 +MODULE_RELEASE_python36= 1 MODULE_CONFARGS_python36= python --config=python3.6-config MODULE_MAKEARGS_python36= python3.6 diff --git a/pkg/deb/Makefile.ruby b/pkg/deb/Makefile.ruby index 48ac4ede..1cb6baab 100644 --- a/pkg/deb/Makefile.ruby +++ b/pkg/deb/Makefile.ruby @@ -4,7 +4,7 @@ MODULE_SUFFIX_ruby= ruby MODULE_SUMMARY_ruby= Ruby module for NGINX Unit MODULE_VERSION_ruby= $(VERSION) -MODULE_RELEASE_ruby= 2 +MODULE_RELEASE_ruby= 1 MODULE_CONFARGS_ruby= ruby MODULE_MAKEARGS_ruby= ruby diff --git a/pkg/docker/Makefile b/pkg/docker/Makefile index 319e14c0..140ac5b3 100644 --- a/pkg/docker/Makefile +++ b/pkg/docker/Makefile @@ -2,7 +2,7 @@ DEFAULT_VERSION := $(shell grep 'define NXT_VERSION' ../../src/nxt_main.h \ | sed -e 's/^.*"\(.*\)".*/\1/') -DEFAULT_RELEASE := 2 +DEFAULT_RELEASE := 1 VERSION ?= $(DEFAULT_VERSION) RELEASE ?= $(DEFAULT_RELEASE) diff --git a/pkg/rpm/Makefile b/pkg/rpm/Makefile index 5eb4213d..ef7f3361 100644 --- a/pkg/rpm/Makefile +++ b/pkg/rpm/Makefile @@ -3,7 +3,7 @@ DEFAULT_VERSION := $(shell grep 'define NXT_VERSION' ../../src/nxt_main.h \ | sed -e 's/^.*"\(.*\)".*/\1/') -DEFAULT_RELEASE := 2 +DEFAULT_RELEASE := 1 VERSION ?= $(DEFAULT_VERSION) RELEASE ?= $(DEFAULT_RELEASE) diff --git a/pkg/rpm/Makefile.go b/pkg/rpm/Makefile.go index a5735c12..40ebf8fb 100644 --- a/pkg/rpm/Makefile.go +++ b/pkg/rpm/Makefile.go @@ -4,7 +4,7 @@ MODULE_SUFFIX_go= go MODULE_SUMMARY_go= Go module for NGINX Unit MODULE_VERSION_go= $(VERSION) -MODULE_RELEASE_go= 2 +MODULE_RELEASE_go= 1 MODULE_CONFARGS_go= go --go-path=%{gopath} MODULE_MAKEARGS_go= go diff --git a/pkg/rpm/Makefile.perl b/pkg/rpm/Makefile.perl index fed66e58..90259e9e 100644 --- a/pkg/rpm/Makefile.perl +++ b/pkg/rpm/Makefile.perl @@ -4,7 +4,7 @@ MODULE_SUFFIX_perl= perl MODULE_SUMMARY_perl= Perl module for NGINX Unit MODULE_VERSION_perl= $(VERSION) -MODULE_RELEASE_perl= 2 +MODULE_RELEASE_perl= 1 MODULE_CONFARGS_perl= perl MODULE_MAKEARGS_perl= perl diff --git a/pkg/rpm/Makefile.php b/pkg/rpm/Makefile.php index 1235777f..b4f093b7 100644 --- a/pkg/rpm/Makefile.php +++ b/pkg/rpm/Makefile.php @@ -4,7 +4,7 @@ MODULE_SUFFIX_php= php MODULE_SUMMARY_php= PHP module for NGINX Unit MODULE_VERSION_php= $(VERSION) -MODULE_RELEASE_php= 2 +MODULE_RELEASE_php= 1 MODULE_CONFARGS_php= php MODULE_MAKEARGS_php= php diff --git a/pkg/rpm/Makefile.python b/pkg/rpm/Makefile.python index e40ba6b8..0b0eb7bd 100644 --- a/pkg/rpm/Makefile.python +++ b/pkg/rpm/Makefile.python @@ -4,7 +4,7 @@ MODULE_SUFFIX_python= python MODULE_SUMMARY_python= Python module for NGINX Unit MODULE_VERSION_python= $(VERSION) -MODULE_RELEASE_python= 2 +MODULE_RELEASE_python= 1 MODULE_CONFARGS_python= python MODULE_MAKEARGS_python= python diff --git a/pkg/rpm/Makefile.python27 b/pkg/rpm/Makefile.python27 index c0c354d5..7d15bdd9 100644 --- a/pkg/rpm/Makefile.python27 +++ b/pkg/rpm/Makefile.python27 @@ -4,7 +4,7 @@ MODULE_SUFFIX_python27= python2.7 MODULE_SUMMARY_python27= Python 2.7 module for NGINX Unit MODULE_VERSION_python27= $(VERSION) -MODULE_RELEASE_python27= 2 +MODULE_RELEASE_python27= 1 MODULE_CONFARGS_python27= python --config=python2.7-config MODULE_MAKEARGS_python27= python2.7 diff --git a/pkg/rpm/Makefile.python34 b/pkg/rpm/Makefile.python34 index af37dea3..152007a2 100644 --- a/pkg/rpm/Makefile.python34 +++ b/pkg/rpm/Makefile.python34 @@ -4,7 +4,7 @@ MODULE_SUFFIX_python34= python3.4 MODULE_SUMMARY_python34= Python 3.4 module for NGINX Unit MODULE_VERSION_python34= $(VERSION) -MODULE_RELEASE_python34= 2 +MODULE_RELEASE_python34= 1 MODULE_CONFARGS_python34= python --config=python3.4-config MODULE_MAKEARGS_python34= python3.4 diff --git a/pkg/rpm/Makefile.python35 b/pkg/rpm/Makefile.python35 index 4837fc5d..3f075702 100644 --- a/pkg/rpm/Makefile.python35 +++ b/pkg/rpm/Makefile.python35 @@ -4,7 +4,7 @@ MODULE_SUFFIX_python35= python3.5 MODULE_SUMMARY_python35= Python 3.5 module for NGINX Unit MODULE_VERSION_python35= $(VERSION) -MODULE_RELEASE_python35= 2 +MODULE_RELEASE_python35= 1 MODULE_CONFARGS_python35= python --config=python3.5-config MODULE_MAKEARGS_python35= python3.5 diff --git a/pkg/rpm/Makefile.python36 b/pkg/rpm/Makefile.python36 index 7d80493a..fd55840e 100644 --- a/pkg/rpm/Makefile.python36 +++ b/pkg/rpm/Makefile.python36 @@ -4,7 +4,7 @@ MODULE_SUFFIX_python36= python3.6 MODULE_SUMMARY_python36= Python 3.6 module for NGINX Unit MODULE_VERSION_python36= $(VERSION) -MODULE_RELEASE_python36= 2 +MODULE_RELEASE_python36= 1 MODULE_CONFARGS_python36= python --config=python3.6-config MODULE_MAKEARGS_python36= python3.6 diff --git a/pkg/rpm/Makefile.ruby b/pkg/rpm/Makefile.ruby index 3816d654..5702fb44 100644 --- a/pkg/rpm/Makefile.ruby +++ b/pkg/rpm/Makefile.ruby @@ -4,7 +4,7 @@ MODULE_SUFFIX_ruby= ruby MODULE_SUMMARY_ruby= Ruby module for NGINX Unit MODULE_VERSION_ruby= $(VERSION) -MODULE_RELEASE_ruby= 2 +MODULE_RELEASE_ruby= 1 MODULE_CONFARGS_ruby= ruby MODULE_MAKEARGS_ruby= ruby -- cgit From a1abebd5b919be3b19f1400b127ddd6acd2c825f Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Thu, 25 Oct 2018 17:49:10 +0300 Subject: Generated Dockerfiles for Unit 1.5. --- 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 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pkg/docker/Dockerfile.full b/pkg/docker/Dockerfile.full index 1ccd4350..2ccfc16c 100644 --- a/pkg/docker/Dockerfile.full +++ b/pkg/docker/Dockerfile.full @@ -2,7 +2,7 @@ FROM debian:stretch-slim LABEL maintainer="NGINX Docker Maintainers " -ENV UNIT_VERSION 1.4-2~stretch +ENV UNIT_VERSION 1.5-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 20b5dea8..aa915518 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.4-2~stretch +ENV UNIT_VERSION 1.5-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 a87033c1..e623182b 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.4-2~stretch +ENV UNIT_VERSION 1.5-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.minimal b/pkg/docker/Dockerfile.minimal index 8fe65bfc..0ff59411 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.4-2~stretch +ENV UNIT_VERSION 1.5-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.perl5.24 b/pkg/docker/Dockerfile.perl5.24 index 53b650c0..06067fc7 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.4-2~stretch +ENV UNIT_VERSION 1.5-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.php7.0 b/pkg/docker/Dockerfile.php7.0 index e20c2908..a6b816bf 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.4-2~stretch +ENV UNIT_VERSION 1.5-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.python2.7 b/pkg/docker/Dockerfile.python2.7 index 8bd7d9df..b02fe194 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.4-2~stretch +ENV UNIT_VERSION 1.5-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.python3.5 b/pkg/docker/Dockerfile.python3.5 index 53e72e2b..32ecfcf5 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.4-2~stretch +ENV UNIT_VERSION 1.5-1~stretch RUN set -x \ && apt-get update \ diff --git a/pkg/docker/Dockerfile.ruby2.3 b/pkg/docker/Dockerfile.ruby2.3 index 84dc10d0..ce5fefda 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.4-2~stretch +ENV UNIT_VERSION 1.5-1~stretch RUN set -x \ && apt-get update \ -- cgit From fd99a738e586326ee5b40a6bc3d09c64b18f394a Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Thu, 25 Oct 2018 18:55:39 +0300 Subject: Added tag 1.5 for changeset b3dee0cc5a4e --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index b451eb11..c755a46f 100644 --- a/.hgtags +++ b/.hgtags @@ -10,3 +10,4 @@ d2fcec5b0fa3b0e8da1945aa240d23be3bf94309 0.7 fbe7f5a3867e9559ef0884786fe5150aa60414e6 1.2 b3cf22b8a17e0e35ca80decb03ed2cceb662c3de 1.3 8f4524a9cf87fbddf626302da071f5055cf33f28 1.4 +b3dee0cc5a4edd046345511769b5cfec49044f1c 1.5 -- cgit