summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_unit.c
diff options
context:
space:
mode:
authorMax Romanov <max.romanov@nginx.com>2020-08-11 21:48:16 +0300
committerMax Romanov <max.romanov@nginx.com>2020-08-11 21:48:16 +0300
commitacb0cca49def92563d9b221d818b541b60e30eaa (patch)
tree602022eab972be03bc2f42797f7f9f95f9be55c9 /src/nxt_unit.c
parent8cf522bf2d8c2d3bcef88ab86c93e06c6afcb6ae (diff)
downloadunit-acb0cca49def92563d9b221d818b541b60e30eaa.tar.gz
unit-acb0cca49def92563d9b221d818b541b60e30eaa.tar.bz2
Moving file descriptor blocking to libunit.
The default libunit behavior relies on blocking the recv() call for port file descriptors, which an application may override if needed. For external applications, port file descriptors were toggled to blocking mode before the exec() call. If the exec() call failed, descriptor remained blocked, so the process hanged while trying to read from it. This patch moves file descriptor mode switch inside libunit.
Diffstat (limited to 'src/nxt_unit.c')
-rw-r--r--src/nxt_unit.c50
1 files changed, 39 insertions, 11 deletions
diff --git a/src/nxt_unit.c b/src/nxt_unit.c
index 990c789c..b063058f 100644
--- a/src/nxt_unit.c
+++ b/src/nxt_unit.c
@@ -171,6 +171,7 @@ static int nxt_unit_port_queue_recv(nxt_unit_port_t *port,
static int nxt_unit_app_queue_recv(nxt_unit_port_t *port,
nxt_unit_read_buf_t *rbuf);
nxt_inline int nxt_unit_close(int fd);
+static int nxt_unit_fd_blocking(int fd);
static int nxt_unit_port_hash_add(nxt_lvlhsh_t *port_hash,
nxt_unit_port_t *port);
@@ -413,6 +414,7 @@ nxt_unit_init(nxt_unit_init_t *init)
}
queue_fd = -1;
+ mem = MAP_FAILED;
if (init->ready_port.id.pid != 0
&& init->ready_stream != 0
@@ -450,6 +452,11 @@ nxt_unit_init(nxt_unit_init_t *init)
ctx = &lib->main_ctx.ctx;
+ rc = nxt_unit_fd_blocking(router_port.out_fd);
+ if (nxt_slow_path(rc != NXT_UNIT_OK)) {
+ goto fail;
+ }
+
lib->router_port = nxt_unit_add_port(ctx, &router_port, NULL);
if (nxt_slow_path(lib->router_port == NULL)) {
nxt_unit_alert(NULL, "failed to add router_port");
@@ -473,12 +480,20 @@ nxt_unit_init(nxt_unit_init_t *init)
nxt_port_queue_init(mem);
+ rc = nxt_unit_fd_blocking(read_port.in_fd);
+ if (nxt_slow_path(rc != NXT_UNIT_OK)) {
+ goto fail;
+ }
+
lib->main_ctx.read_port = nxt_unit_add_port(ctx, &read_port, mem);
if (nxt_slow_path(lib->main_ctx.read_port == NULL)) {
nxt_unit_alert(NULL, "failed to add read_port");
- munmap(mem, sizeof(nxt_port_queue_t));
+ goto fail;
+ }
+ rc = nxt_unit_fd_blocking(ready_port.out_fd);
+ if (nxt_slow_path(rc != NXT_UNIT_OK)) {
goto fail;
}
@@ -486,8 +501,6 @@ nxt_unit_init(nxt_unit_init_t *init)
if (nxt_slow_path(rc != NXT_UNIT_OK)) {
nxt_unit_alert(NULL, "failed to send READY message");
- munmap(mem, sizeof(nxt_port_queue_t));
-
goto fail;
}
@@ -498,6 +511,10 @@ nxt_unit_init(nxt_unit_init_t *init)
fail:
+ if (mem != MAP_FAILED) {
+ munmap(mem, sizeof(nxt_port_queue_t));
+ }
+
if (queue_fd != -1) {
nxt_unit_close(queue_fd);
}
@@ -1064,7 +1081,6 @@ fail:
static int
nxt_unit_process_new_port(nxt_unit_ctx_t *ctx, nxt_unit_recv_msg_t *recv_msg)
{
- int nb;
void *mem;
nxt_unit_impl_t *lib;
nxt_unit_port_t new_port, *port;
@@ -1103,13 +1119,7 @@ nxt_unit_process_new_port(nxt_unit_ctx_t *ctx, nxt_unit_recv_msg_t *recv_msg)
MAP_SHARED, recv_msg->fd2, 0);
} else {
- nb = 0;
-
- if (nxt_slow_path(ioctl(recv_msg->fd, FIONBIO, &nb) == -1)) {
- nxt_unit_alert(ctx, "#%"PRIu32": new_port: ioctl(%d, FIONBIO, 0) "
- "failed: %s (%d)",
- recv_msg->stream, recv_msg->fd, strerror(errno), errno);
-
+ if (nxt_slow_path(nxt_unit_fd_blocking(recv_msg->fd) != NXT_UNIT_OK)) {
return NXT_UNIT_ERROR;
}
@@ -5919,6 +5929,24 @@ nxt_unit_close(int fd)
}
+static int
+nxt_unit_fd_blocking(int fd)
+{
+ int nb;
+
+ nb = 0;
+
+ if (nxt_slow_path(ioctl(fd, FIONBIO, &nb) == -1)) {
+ nxt_unit_alert(NULL, "ioctl(%d, FIONBIO, 0) failed: %s (%d)",
+ fd, strerror(errno), errno);
+
+ return NXT_UNIT_ERROR;
+ }
+
+ return NXT_UNIT_OK;
+}
+
+
static nxt_int_t
nxt_unit_port_hash_test(nxt_lvlhsh_query_t *lhq, void *data)
{