From a31df988bb59e438e0eca9f7fb057a2c8ff7b54b Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Thu, 26 Dec 2019 16:23:11 -0800 Subject: fixes #1037 http client crashes (pthread lock bugs) This reference counts both TCP and IPC dialers running on POSIX configurations, as we need to take care not to destroy the dialer until any streams associated with are completely destroyed. --- src/platform/posix/posix_ipc.h | 3 +++ src/platform/posix/posix_ipcconn.c | 4 ++++ src/platform/posix/posix_ipcdial.c | 32 ++++++++++++++++++++++++++++++-- src/platform/posix/posix_tcp.h | 1 + src/platform/posix/posix_tcpconn.c | 3 +++ src/platform/posix/posix_tcpdial.c | 33 +++++++++++++++++++++++++++++++-- 6 files changed, 72 insertions(+), 4 deletions(-) (limited to 'src/platform') diff --git a/src/platform/posix/posix_ipc.h b/src/platform/posix/posix_ipc.h index 7fdff4aa..f0b9b5ef 100644 --- a/src/platform/posix/posix_ipc.h +++ b/src/platform/posix/posix_ipc.h @@ -37,10 +37,13 @@ struct nni_ipc_dialer { bool closed; nni_mtx mtx; nng_sockaddr sa; + int refcnt; + bool fini; }; extern int nni_posix_ipc_init(nni_ipc_conn **, nni_posix_pfd *); extern void nni_posix_ipc_start(nni_ipc_conn *); +extern void nni_posix_ipc_dialer_rele(nni_ipc_dialer *); #endif // NNG_PLATFORM_POSIX diff --git a/src/platform/posix/posix_ipcconn.c b/src/platform/posix/posix_ipcconn.c index f703b583..2b078aa5 100644 --- a/src/platform/posix/posix_ipcconn.c +++ b/src/platform/posix/posix_ipcconn.c @@ -493,6 +493,10 @@ ipc_free(void *arg) nni_mtx_unlock(&c->mtx); nni_mtx_fini(&c->mtx); + if (c->dialer != NULL) { + nni_posix_ipc_dialer_rele(c->dialer); + } + NNI_FREE_STRUCT(c); } diff --git a/src/platform/posix/posix_ipcdial.c b/src/platform/posix/posix_ipcdial.c index 3ce8c401..50c7a897 100644 --- a/src/platform/posix/posix_ipcdial.c +++ b/src/platform/posix/posix_ipcdial.c @@ -49,13 +49,40 @@ ipc_dialer_close(void *arg) nni_mtx_unlock(&d->mtx); } +static void +ipc_dialer_fini(ipc_dialer *d) +{ + nni_mtx_fini(&d->mtx); + NNI_FREE_STRUCT(d); +} + static void ipc_dialer_free(void *arg) { ipc_dialer *d = arg; + ipc_dialer_close(d); - nni_mtx_fini(&d->mtx); - NNI_FREE_STRUCT(d); + nni_mtx_lock(&d->mtx); + d->fini = true; + if (d->refcnt) { + nni_mtx_unlock(&d->mtx); + return; + } + nni_mtx_unlock(&d->mtx); + ipc_dialer_fini(d); +} + +void +nni_posix_ipc_dialer_rele(ipc_dialer *d) +{ + nni_mtx_lock(&d->mtx); + d->refcnt--; + if ((d->refcnt > 0) || (!d->fini)) { + nni_mtx_unlock(&d->mtx); + return; + } + nni_mtx_unlock(&d->mtx); + ipc_dialer_fini(d); } static void @@ -174,6 +201,7 @@ ipc_dialer_dial(void *arg, nni_aio *aio) nni_posix_pfd_set_cb(pfd, ipc_dialer_cb, c); nni_mtx_lock(&d->mtx); + d->refcnt++; if (d->closed) { rv = NNG_ECLOSED; goto error; diff --git a/src/platform/posix/posix_tcp.h b/src/platform/posix/posix_tcp.h index 9c7d0684..e1a70bc3 100644 --- a/src/platform/posix/posix_tcp.h +++ b/src/platform/posix/posix_tcp.h @@ -29,5 +29,6 @@ struct nni_tcp_conn { }; extern int nni_posix_tcp_init(nni_tcp_conn **, nni_posix_pfd *); extern void nni_posix_tcp_start(nni_tcp_conn *, int, int); +extern void nni_posix_tcp_dialer_rele(nni_tcp_dialer *); #endif // PLATFORM_POSIX_TCP_H \ No newline at end of file diff --git a/src/platform/posix/posix_tcpconn.c b/src/platform/posix/posix_tcpconn.c index d4ffbf21..625fd7fd 100644 --- a/src/platform/posix/posix_tcpconn.c +++ b/src/platform/posix/posix_tcpconn.c @@ -208,6 +208,9 @@ tcp_fini(void *arg) nni_mtx_unlock(&c->mtx); nni_mtx_fini(&c->mtx); + if (c->dialer != NULL) { + nni_posix_tcp_dialer_rele(c->dialer); + } NNI_FREE_STRUCT(c); } diff --git a/src/platform/posix/posix_tcpdial.c b/src/platform/posix/posix_tcpdial.c index 457a64ea..418eb17e 100644 --- a/src/platform/posix/posix_tcpdial.c +++ b/src/platform/posix/posix_tcpdial.c @@ -31,6 +31,8 @@ struct nni_tcp_dialer { struct sockaddr_storage src; size_t srclen; nni_mtx mtx; + int refcnt; + bool fini; }; // Dialer stuff. @@ -71,12 +73,38 @@ nni_tcp_dialer_close(nni_tcp_dialer *d) nni_mtx_unlock(&d->mtx); } +static void +tcp_dialer_fini(nni_tcp_dialer *d) +{ + nni_mtx_fini(&d->mtx); + NNI_FREE_STRUCT(d); +} + void nni_tcp_dialer_fini(nni_tcp_dialer *d) { nni_tcp_dialer_close(d); - nni_mtx_fini(&d->mtx); - NNI_FREE_STRUCT(d); + nni_mtx_lock(&d->mtx); + d->fini = true; + if (d->refcnt) { + nni_mtx_unlock(&d->mtx); + return; + } + nni_mtx_unlock(&d->mtx); + tcp_dialer_fini(d); +} + +void +nni_posix_tcp_dialer_rele(nni_tcp_dialer *d) +{ + nni_mtx_lock(&d->mtx); + d->refcnt--; + if ((d->refcnt > 0) || (!d->fini)) { + nni_mtx_unlock(&d->mtx); + return; + } + nni_mtx_unlock(&d->mtx); + tcp_dialer_fini(d); } static void @@ -203,6 +231,7 @@ nni_tcp_dial(nni_tcp_dialer *d, nni_aio *aio) nni_posix_pfd_set_cb(pfd, tcp_dialer_cb, c); nni_mtx_lock(&d->mtx); + d->refcnt++; if (d->closed) { rv = NNG_ECLOSED; goto error; -- cgit v1.2.3-70-g09d2