summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2019-12-26 16:23:11 -0800
committerGarrett D'Amore <garrett@damore.org>2019-12-26 16:56:33 -0800
commita31df988bb59e438e0eca9f7fb057a2c8ff7b54b (patch)
treee5f7ba187069125e227235473da6290d234aeb43
parentd590eceab74772a8d5fa50c94074b09927577ee4 (diff)
downloadnng-a31df988bb59e438e0eca9f7fb057a2c8ff7b54b.tar.gz
nng-a31df988bb59e438e0eca9f7fb057a2c8ff7b54b.tar.bz2
nng-a31df988bb59e438e0eca9f7fb057a2c8ff7b54b.zip
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.
-rw-r--r--src/platform/posix/posix_ipc.h3
-rw-r--r--src/platform/posix/posix_ipcconn.c4
-rw-r--r--src/platform/posix/posix_ipcdial.c32
-rw-r--r--src/platform/posix/posix_tcp.h1
-rw-r--r--src/platform/posix/posix_tcpconn.c3
-rw-r--r--src/platform/posix/posix_tcpdial.c33
6 files changed, 72 insertions, 4 deletions
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
@@ -50,12 +50,39 @@ ipc_dialer_close(void *arg)
}
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;