diff options
| author | Garrett D'Amore <garrett@damore.org> | 2024-12-12 17:55:48 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2024-12-12 17:55:48 -0800 |
| commit | 81f5d3c6268ff91ee9c36c4cb34f6f9bfd54740d (patch) | |
| tree | f9f21aa66bd22cfd95ae0c4b8abe57036c8fce0d /src/platform/windows/win_tcpconn.c | |
| parent | 371eedeeb6fafe628ae89b9ad2690fa3d6a57e8a (diff) | |
| download | nng-81f5d3c6268ff91ee9c36c4cb34f6f9bfd54740d.tar.gz nng-81f5d3c6268ff91ee9c36c4cb34f6f9bfd54740d.tar.bz2 nng-81f5d3c6268ff91ee9c36c4cb34f6f9bfd54740d.zip | |
streams: add explicit stop functions
This allows us to explicitly stop streams, dialers, and listeners,
before we start tearing down things. This hopefully will be useful
in resolving use-after-free bugs in http, tls, and websockets.
The new functions are not yet documented, but they are
nng_stream_stop, nng_stream_dialer_stop, and nng_stream_listener_stop.
They should be called after close, and before free. The close
functions now close without blocking, but the stop function is
allowed to block.
Diffstat (limited to 'src/platform/windows/win_tcpconn.c')
| -rw-r--r-- | src/platform/windows/win_tcpconn.c | 26 |
1 files changed, 12 insertions, 14 deletions
diff --git a/src/platform/windows/win_tcpconn.c b/src/platform/windows/win_tcpconn.c index 3f3acd17..2f2fd378 100644 --- a/src/platform/windows/win_tcpconn.c +++ b/src/platform/windows/win_tcpconn.c @@ -180,6 +180,7 @@ tcp_send_start(nni_tcp_conn *c) return; } } + nni_cv_wake(&c->cv); } static void @@ -266,17 +267,6 @@ tcp_close(void *arg) closesocket(s); } } - now = nni_clock(); - // wait up to a maximum of 10 seconds before assuming something is - // badly amiss. from what we can tell, this doesn't happen, and we do - // see the timer expire properly, but this safeguard can prevent a - // hang. - while ((c->recving || c->sending) && - ((nni_clock() - now) < (NNI_SECOND * 10))) { - nni_mtx_unlock(&c->mtx); - nni_msleep(1); - nni_mtx_lock(&c->mtx); - } nni_mtx_unlock(&c->mtx); } @@ -369,21 +359,28 @@ tcp_set(void *arg, const char *name, const void *buf, size_t sz, nni_type t) } static void -tcp_free(void *arg) +tcp_stop(void *arg) { nni_tcp_conn *c = arg; tcp_close(c); nni_mtx_lock(&c->mtx); - while ((!nni_list_empty(&c->recv_aios)) || + while (c->recving || c->sending || (!nni_list_empty(&c->recv_aios)) || (!nni_list_empty(&c->send_aios))) { nni_cv_wait(&c->cv); } nni_mtx_unlock(&c->mtx); - if (c->s != INVALID_SOCKET) { closesocket(c->s); } +} + +static void +tcp_free(void *arg) +{ + nni_tcp_conn *c = arg; + tcp_stop(c); + nni_cv_fini(&c->cv); nni_mtx_fini(&c->mtx); NNI_FREE_STRUCT(c); @@ -410,6 +407,7 @@ nni_win_tcp_init(nni_tcp_conn **connp, SOCKET s) nni_aio_list_init(&c->send_aios); c->conn_aio = NULL; c->ops.s_close = tcp_close; + c->ops.s_stop = tcp_stop; c->ops.s_free = tcp_free; c->ops.s_send = tcp_send; c->ops.s_recv = tcp_recv; |
