aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2020-05-06 22:07:42 -0700
committerGarrett D'Amore <garrett@damore.org>2020-05-17 18:32:11 -0700
commitb7a11a0e9e5655da3198e36495d143ea03de91bb (patch)
tree02773c4d8fd8417aee7a5908decc53422748ef10 /src
parent1a00f65db42d4c92eee28356daa08c9adf4408fe (diff)
downloadnng-b7a11a0e9e5655da3198e36495d143ea03de91bb.tar.gz
nng-b7a11a0e9e5655da3198e36495d143ea03de91bb.tar.bz2
nng-b7a11a0e9e5655da3198e36495d143ea03de91bb.zip
fixes #1236 Deadlock triggered on nng_close
fixes #1219 nng_close occasionally hang on Windows
Diffstat (limited to 'src')
-rw-r--r--src/core/aio.c2
-rw-r--r--src/core/taskq.c14
-rw-r--r--src/core/taskq.h7
-rw-r--r--src/transport/tcp/tcp.c4
4 files changed, 24 insertions, 3 deletions
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
@@ -184,6 +184,20 @@ nni_task_prep(nni_task *task)
}
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)
{
nni_mtx_lock(&task->task_mtx);
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. <info@staysail.tech>
+// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// 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 *);
diff --git a/src/transport/tcp/tcp.c b/src/transport/tcp/tcp.c
index 32df5102..9012a5bc 100644
--- a/src/transport/tcp/tcp.c
+++ b/src/transport/tcp/tcp.c
@@ -547,8 +547,8 @@ tcptran_pipe_recv_start(tcptran_pipe *p)
if (p->closed) {
nni_aio *aio;
- while ((aio = nni_list_first(&p->sendq)) != NULL) {
- nni_list_remove(&p->sendq, aio);
+ while ((aio = nni_list_first(&p->recvq)) != NULL) {
+ nni_list_remove(&p->recvq, aio);
nni_aio_finish_error(aio, NNG_ECLOSED);
}
return;