aboutsummaryrefslogtreecommitdiff
path: root/src/platform/windows/win_ipc.c
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2017-08-04 17:17:42 -0700
committerGarrett D'Amore <garrett@damore.org>2017-08-04 21:20:00 -0700
commitdc334d7193a2a0bc0194221b853a37e1be7f5b9a (patch)
tree1eebf2773745a3a25e8a071fbe4f51cd5490d4e4 /src/platform/windows/win_ipc.c
parent6887900ae033add30ee0151b72abe927c5239588 (diff)
downloadnng-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/platform/windows/win_ipc.c')
-rw-r--r--src/platform/windows/win_ipc.c58
1 files changed, 22 insertions, 36 deletions
diff --git a/src/platform/windows/win_ipc.c b/src/platform/windows/win_ipc.c
index bd9ce26d..c9eb20ec 100644
--- a/src/platform/windows/win_ipc.c
+++ b/src/platform/windows/win_ipc.c
@@ -65,7 +65,7 @@ nni_win_ipc_pipe_start(nni_win_event *evt, nni_aio *aio)
NNI_ASSERT(aio->a_iov[0].iov_buf != NULL);
if (pipe->p == INVALID_HANDLE_VALUE) {
- evt->status = ERROR_INVALID_HANDLE;
+ evt->status = NNG_ECLOSED;
evt->count = 0;
return (1);
}
@@ -92,7 +92,7 @@ nni_win_ipc_pipe_start(nni_win_event *evt, nni_aio *aio)
}
if ((!ok) && ((rv = GetLastError()) != ERROR_IO_PENDING)) {
// Synchronous failure.
- evt->status = rv;
+ evt->status = nni_win_error(rv);
evt->count = 0;
return (1);
}
@@ -108,13 +108,7 @@ nni_win_ipc_pipe_cancel(nni_win_event *evt)
{
nni_plat_ipc_pipe *pipe = evt->ptr;
- if (CancelIoEx(pipe->p, &evt->olpd)) {
- DWORD cnt;
-
- // If we canceled, make sure that we've completely
- // finished with the overlapped.
- GetOverlappedResult(pipe->p, &evt->olpd, &cnt, TRUE);
- }
+ CancelIoEx(pipe->p, &evt->olpd);
}
static void
@@ -146,7 +140,7 @@ nni_win_ipc_pipe_finish(nni_win_event *evt, nni_aio *aio)
}
// All done; hopefully successfully.
- nni_aio_finish(aio, nni_win_error(rv), aio->a_count);
+ nni_aio_finish(aio, rv, aio->a_count);
}
static int
@@ -294,7 +288,7 @@ nni_win_ipc_acc_finish(nni_win_event *evt, nni_aio *aio)
HANDLE newp, oldp;
if ((rv = evt->status) != 0) {
- nni_aio_finish(aio, nni_win_error(rv), 0);
+ nni_aio_finish_error(aio, rv);
return;
}
@@ -308,7 +302,7 @@ nni_win_ipc_acc_finish(nni_win_event *evt, nni_aio *aio)
// We connected, but as we cannot get a new pipe,
// we have to disconnect the old one.
DisconnectNamedPipe(ep->p);
- nni_aio_finish(aio, rv, 0);
+ nni_aio_finish_error(aio, rv);
return;
}
if ((rv = nni_win_iocp_register(newp)) != 0) {
@@ -317,7 +311,7 @@ nni_win_ipc_acc_finish(nni_win_event *evt, nni_aio *aio)
// And discard the half-baked new one.
DisconnectNamedPipe(newp);
(void) CloseHandle(newp);
- nni_aio_finish(aio, rv, 0);
+ nni_aio_finish_error(aio, rv);
return;
}
@@ -329,14 +323,11 @@ nni_win_ipc_acc_finish(nni_win_event *evt, nni_aio *aio)
// the old one, since failed to be able to use it.
DisconnectNamedPipe(oldp);
(void) CloseHandle(oldp);
- nni_aio_finish(aio, rv, 0);
+ nni_aio_finish_error(aio, rv);
return;
}
- // What if the pipe is already finished?
- if (nni_aio_finish_pipe(aio, 0, pipe) != 0) {
- nni_plat_ipc_pipe_fini(pipe);
- }
+ nni_aio_finish_pipe(aio, pipe);
}
static void
@@ -344,13 +335,7 @@ nni_win_ipc_acc_cancel(nni_win_event *evt)
{
nni_plat_ipc_ep *ep = evt->ptr;
- if (CancelIoEx(ep->p, &evt->olpd)) {
- DWORD cnt;
-
- // If we canceled, make sure that we've completely
- // finished with the overlapped.
- GetOverlappedResult(ep->p, &evt->olpd, &cnt, TRUE);
- }
+ (void) CancelIoEx(ep->p, &evt->olpd);
// Just to be sure.
(void) DisconnectNamedPipe(ep->p);
}
@@ -376,7 +361,7 @@ nni_win_ipc_acc_start(nni_win_event *evt, nni_aio *aio)
default:
// Fast-fail (synchronous).
- evt->status = rv;
+ evt->status = nni_win_error(rv);
evt->count = 0;
return (1);
}
@@ -468,9 +453,7 @@ nni_win_ipc_conn_thr(void *arg)
((rv = nni_win_iocp_register(p)) != 0)) {
goto fail;
}
- if (rv = nni_aio_finish_pipe(aio, 0, pipe) != 0) {
- nni_plat_ipc_pipe_fini(pipe);
- }
+ nni_aio_finish_pipe(aio, pipe);
continue;
fail:
@@ -481,7 +464,7 @@ nni_win_ipc_conn_thr(void *arg)
if (pipe != NULL) {
nni_plat_ipc_pipe_fini(pipe);
}
- nni_aio_finish(aio, rv, 0);
+ nni_aio_finish_error(aio, rv);
}
if (nni_list_empty(&w->waiters)) {
@@ -496,16 +479,19 @@ nni_win_ipc_conn_thr(void *arg)
}
static void
-nni_win_ipc_conn_cancel(nni_aio *aio)
+nni_win_ipc_conn_cancel(nni_aio *aio, int rv)
{
nni_win_ipc_conn_work *w = &nni_win_ipc_connecter;
nni_plat_ipc_ep * ep = aio->a_prov_data;
nni_mtx_lock(&w->mtx);
- ep->con_aio = NULL;
- if (nni_list_active(&w->waiters, ep)) {
- nni_list_remove(&w->waiters, ep);
- nni_cv_wake(&w->cv);
+ if (aio == ep->con_aio) {
+ ep->con_aio = NULL;
+ if (nni_list_active(&w->waiters, ep)) {
+ nni_list_remove(&w->waiters, ep);
+ nni_cv_wake(&w->cv);
+ }
+ nni_aio_finish_error(aio, rv);
}
nni_mtx_unlock(&w->mtx);
}
@@ -556,7 +542,7 @@ nni_plat_ipc_ep_close(nni_plat_ipc_ep *ep)
}
if ((aio = ep->con_aio) != NULL) {
ep->con_aio = NULL;
- nni_aio_finish(aio, NNG_ECLOSED, 0);
+ nni_aio_finish_error(aio, NNG_ECLOSED);
}
nni_mtx_unlock(&w->mtx);
break;