diff options
| author | Garrett D'Amore <garrett@damore.org> | 2017-08-04 17:17:42 -0700 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2017-08-04 21:20:00 -0700 |
| commit | dc334d7193a2a0bc0194221b853a37e1be7f5b9a (patch) | |
| tree | 1eebf2773745a3a25e8a071fbe4f51cd5490d4e4 /src/transport/ipc/ipc.c | |
| parent | 6887900ae033add30ee0151b72abe927c5239588 (diff) | |
| download | nng-dc334d7193a2a0bc0194221b853a37e1be7f5b9a.tar.gz nng-dc334d7193a2a0bc0194221b853a37e1be7f5b9a.tar.bz2 nng-dc334d7193a2a0bc0194221b853a37e1be7f5b9a.zip | |
Refactor AIO logic to close numerous races and reduce complexity.
This passes valgrind 100% clean for both helgrind and deep leak
checks. This represents a complete rethink of how the AIOs work,
and much simpler synchronization; the provider API is a bit simpler
to boot, as a number of failure modes have been simply eliminated.
While here a few other minor bugs were squashed.
Diffstat (limited to 'src/transport/ipc/ipc.c')
| -rw-r--r-- | src/transport/ipc/ipc.c | 69 |
1 files changed, 49 insertions, 20 deletions
diff --git a/src/transport/ipc/ipc.c b/src/transport/ipc/ipc.c index 96dae6de..e8c7968f 100644 --- a/src/transport/ipc/ipc.c +++ b/src/transport/ipc/ipc.c @@ -142,15 +142,20 @@ fail: } static void -nni_ipc_cancel_start(nni_aio *aio) +nni_ipc_cancel_start(nni_aio *aio, int rv) { nni_ipc_pipe *pipe = aio->a_prov_data; nni_mtx_lock(&pipe->mtx); + if (pipe->user_negaio != aio) { + nni_mtx_unlock(&pipe->mtx); + return; + } pipe->user_negaio = NULL; nni_mtx_unlock(&pipe->mtx); - nni_aio_cancel(&pipe->negaio, aio->a_result); + nni_aio_cancel(&pipe->negaio, rv); + nni_aio_finish_error(aio, rv); } static void @@ -239,10 +244,10 @@ nni_ipc_pipe_recv_cb(void *arg) nni_ipc_pipe *pipe = arg; nni_aio * aio; int rv; + nni_msg * msg; nni_mtx_lock(&pipe->mtx); - aio = pipe->user_rxaio; - if (aio == NULL) { + if ((aio = pipe->user_rxaio) == NULL) { // aio was canceled nni_mtx_unlock(&pipe->mtx); return; @@ -257,7 +262,7 @@ nni_ipc_pipe_recv_cb(void *arg) pipe->rxmsg = NULL; } pipe->user_rxaio = NULL; - nni_aio_finish(aio, rv, 0); + nni_aio_finish_error(aio, rv); nni_mtx_unlock(&pipe->mtx); return; } @@ -270,7 +275,7 @@ nni_ipc_pipe_recv_cb(void *arg) // Check to make sure we got msg type 1. if (pipe->rxhead[0] != 1) { - nni_aio_finish(aio, NNG_EPROTO, 0); + nni_aio_finish_error(aio, NNG_EPROTO); nni_mtx_unlock(&pipe->mtx); return; } @@ -282,7 +287,7 @@ nni_ipc_pipe_recv_cb(void *arg) // the caller will shut down the pipe. if (len > pipe->rcvmax) { pipe->user_rxaio = NULL; - nni_aio_finish(aio, NNG_EMSGSIZE, 0); + nni_aio_finish_error(aio, NNG_EMSGSIZE); nni_mtx_unlock(&pipe->mtx); return; } @@ -294,7 +299,7 @@ nni_ipc_pipe_recv_cb(void *arg) // unlikely to be much of an issue though. if ((rv = nng_msg_alloc(&pipe->rxmsg, (size_t) len)) != 0) { pipe->user_rxaio = NULL; - nni_aio_finish(aio, rv, 0); + nni_aio_finish_error(aio, rv); nni_mtx_unlock(&pipe->mtx); return; } @@ -313,22 +318,27 @@ nni_ipc_pipe_recv_cb(void *arg) // Otherwise we got a message read completely. Let the user know the // good news. pipe->user_rxaio = NULL; - aio->a_msg = pipe->rxmsg; + msg = pipe->rxmsg; pipe->rxmsg = NULL; - nni_aio_finish(aio, 0, nni_msg_len(aio->a_msg)); + nni_aio_finish_msg(aio, msg); nni_mtx_unlock(&pipe->mtx); } static void -nni_ipc_cancel_tx(nni_aio *aio) +nni_ipc_cancel_tx(nni_aio *aio, int rv) { nni_ipc_pipe *pipe = aio->a_prov_data; nni_mtx_lock(&pipe->mtx); + if (pipe->user_txaio != aio) { + nni_mtx_unlock(&pipe->mtx); + return; + } pipe->user_txaio = NULL; nni_mtx_unlock(&pipe->mtx); - nni_aio_cancel(&pipe->txaio, aio->a_result); + nni_aio_cancel(&pipe->txaio, rv); + nni_aio_finish_error(aio, rv); } static void @@ -364,15 +374,20 @@ nni_ipc_pipe_send(void *arg, nni_aio *aio) } static void -nni_ipc_cancel_rx(nni_aio *aio) +nni_ipc_cancel_rx(nni_aio *aio, int rv) { nni_ipc_pipe *pipe = aio->a_prov_data; nni_mtx_lock(&pipe->mtx); + if (pipe->user_rxaio != aio) { + nni_mtx_unlock(&pipe->mtx); + return; + } pipe->user_rxaio = NULL; nni_mtx_unlock(&pipe->mtx); - nni_aio_cancel(&pipe->rxaio, aio->a_result); + nni_aio_cancel(&pipe->rxaio, rv); + nni_aio_finish_error(aio, rv); } static void @@ -552,10 +567,18 @@ done: aio = ep->user_aio; ep->user_aio = NULL; - if ((aio == NULL) || (nni_aio_finish_pipe(aio, rv, pipe) != 0)) { - if (pipe != NULL) { - nni_ipc_pipe_fini(pipe); - } + if ((aio != NULL) && (rv == 0)) { + NNI_ASSERT(pipe != NULL); + nni_aio_finish_pipe(aio, pipe); + return; + } + + if (pipe != NULL) { + nni_ipc_pipe_fini(pipe); + } + if (aio != NULL) { + NNI_ASSERT(rv != 0); + nni_aio_finish_error(aio, rv); } } @@ -570,15 +593,21 @@ nni_ipc_ep_cb(void *arg) } static void -nni_ipc_cancel_ep(nni_aio *aio) +nni_ipc_cancel_ep(nni_aio *aio, int rv) { nni_ipc_ep *ep = aio->a_prov_data; + NNI_ASSERT(rv != 0); nni_mtx_lock(&ep->mtx); + if (ep->user_aio != aio) { + nni_mtx_unlock(&ep->mtx); + return; + } ep->user_aio = NULL; nni_mtx_unlock(&ep->mtx); - nni_aio_cancel(&ep->aio, aio->a_result); + nni_aio_cancel(&ep->aio, rv); + nni_aio_finish_error(aio, rv); } static void |
