Skip to content

Commit

Permalink
fixes #1236 Deadlock triggered on nng_close
Browse files Browse the repository at this point in the history
fixes #1219 nng_close occasionally hang on Windows
  • Loading branch information
gdamore committed May 18, 2020
1 parent 1a00f65 commit b7a11a0
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/core/aio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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);
}
Expand Down
14 changes: 14 additions & 0 deletions src/core/taskq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
7 changes: 6 additions & 1 deletion src/core/taskq.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2018 Staysail Systems, Inc. <[email protected]>
// Copyright 2020 Staysail Systems, Inc. <[email protected]>
// Copyright 2018 Capitar IT Group BV <[email protected]>
//
// This software is supplied under the terms of the MIT License, a
Expand Down Expand Up @@ -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 *);

Expand Down
4 changes: 2 additions & 2 deletions src/transport/tcp/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit b7a11a0

Please sign in to comment.