aboutsummaryrefslogtreecommitdiff
path: root/src/core/pipe.c
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2017-07-05 15:51:29 -0700
committerGarrett D'Amore <garrett@damore.org>2017-07-05 15:51:29 -0700
commit372d03889b1398016056d1641d31705b75d97c9a (patch)
treee26d06ee7e07820e8da08e9259832b2ce4180934 /src/core/pipe.c
parent0b08b59786e4af19f57bf00ebc20ee8f96453679 (diff)
downloadnng-372d03889b1398016056d1641d31705b75d97c9a.tar.gz
nng-372d03889b1398016056d1641d31705b75d97c9a.tar.bz2
nng-372d03889b1398016056d1641d31705b75d97c9a.zip
Move IPC negotiation out of connect/accept.
This prevents a slow partner from blocking new connections from being established on the server. Before this a single partner could cause the server to block waiting to complete the negotiation.
Diffstat (limited to 'src/core/pipe.c')
-rw-r--r--src/core/pipe.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/src/core/pipe.c b/src/core/pipe.c
index 08d3dee7..eaf4fa1c 100644
--- a/src/core/pipe.c
+++ b/src/core/pipe.c
@@ -53,6 +53,7 @@ nni_pipe_dtor(void *ptr)
p->p_tran_ops.p_fini(p->p_tran_data);
}
+ nni_aio_fini(&p->p_start_aio);
nni_mtx_fini(&p->p_mtx);
NNI_FREE_STRUCT(p);
}
@@ -170,6 +171,28 @@ nni_pipe_peer(nni_pipe *p)
}
+static void
+nni_pipe_start_cb(void *arg)
+{
+ nni_pipe *p = arg;
+ nni_aio *aio = &p->p_start_aio;
+ int rv;
+
+ nni_mtx_lock(&p->p_mtx);
+ if ((rv = nni_aio_result(aio)) != 0) {
+ nni_mtx_unlock(&p->p_mtx);
+ nni_pipe_stop(p);
+ return;
+ }
+
+ nni_mtx_unlock(&p->p_mtx);
+
+ if ((rv = nni_sock_pipe_ready(p->p_sock, p)) != 0) {
+ nni_pipe_stop(p);
+ }
+}
+
+
int
nni_pipe_create(nni_pipe **pp, nni_ep *ep, nni_sock *sock, nni_tran *tran)
{
@@ -182,6 +205,10 @@ nni_pipe_create(nni_pipe **pp, nni_ep *ep, nni_sock *sock, nni_tran *tran)
if (rv != 0) {
return (rv);
}
+ if ((rv = nni_aio_init(&p->p_start_aio, nni_pipe_start_cb, p)) != 0) {
+ nni_objhash_unref(nni_pipes, p->p_id);
+ return (rv);
+ }
p->p_sock = sock;
p->p_ep = ep;
@@ -225,10 +252,12 @@ nni_pipe_start(nni_pipe *p)
{
int rv;
- if ((rv = nni_sock_pipe_ready(p->p_sock, p)) != 0) {
+ if (p->p_tran_ops.p_start == NULL) {
+ rv = nni_sock_pipe_ready(p->p_sock, p);
return (rv);
}
+ p->p_tran_ops.p_start(p->p_tran_data, &p->p_start_aio);
// XXX: Publish event
return (0);