From b7a11a0e9e5655da3198e36495d143ea03de91bb Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Wed, 6 May 2020 22:07:42 -0700 Subject: fixes #1236 Deadlock triggered on nng_close fixes #1219 nng_close occasionally hang on Windows --- src/core/aio.c | 2 ++ src/core/taskq.c | 14 ++++++++++++++ src/core/taskq.h | 7 ++++++- 3 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/aio.c b/src/core/aio.c index 2e38c323..ea2203f2 100644 --- a/src/core/aio.c +++ b/src/core/aio.c @@ -328,6 +328,7 @@ nni_aio_schedule(nni_aio *aio, nni_aio_cancelfn cancelfn, void *data) // Convert the relative timeout to an absolute timeout. switch (aio->a_timeout) { case NNG_DURATION_ZERO: + nni_task_abort(&aio->a_task); return (NNG_ETIMEDOUT); case NNG_DURATION_INFINITE: case NNG_DURATION_DEFAULT: @@ -341,6 +342,7 @@ nni_aio_schedule(nni_aio *aio, nni_aio_cancelfn cancelfn, void *data) nni_mtx_lock(&nni_aio_lk); if (aio->a_stop) { + nni_task_abort(&aio->a_task); nni_mtx_unlock(&nni_aio_lk); return (NNG_ECLOSED); } diff --git a/src/core/taskq.c b/src/core/taskq.c index e63e33c7..fbd93ebe 100644 --- a/src/core/taskq.c +++ b/src/core/taskq.c @@ -183,6 +183,20 @@ nni_task_prep(nni_task *task) nni_mtx_unlock(&task->task_mtx); } +void +nni_task_abort(nni_task *task) +{ + // This is called when unscheduling the task. + nni_mtx_lock(&task->task_mtx); + if (task->task_prep) { + task->task_prep = false; + task->task_busy--; + if (task->task_busy == 0) { + nni_cv_wake(&task->task_cv); + } + } + nni_mtx_unlock(&task->task_mtx); +} void nni_task_wait(nni_task *task) { diff --git a/src/core/taskq.h b/src/core/taskq.h index 53f9d35b..9cabfd9b 100644 --- a/src/core/taskq.h +++ b/src/core/taskq.h @@ -1,5 +1,5 @@ // -// Copyright 2018 Staysail Systems, Inc. +// Copyright 2020 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -38,6 +38,11 @@ extern void nni_task_exec(nni_task *); // nni_task_exec). extern void nni_task_prep(nni_task *); +// nni_task_abort is called to undo the effect of nni_task_prep, +// basically. The aio framework uses this when nni_aio_schedule() +// returns an error. +extern void nni_task_abort(nni_task *); + extern void nni_task_wait(nni_task *); extern void nni_task_init(nni_task *, nni_taskq *, nni_cb, void *); -- cgit v1.2.3-70-g09d2