aboutsummaryrefslogtreecommitdiff
path: root/src/platform/posix/posix_tcpconn.c
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2024-12-12 17:55:48 -0800
committerGarrett D'Amore <garrett@damore.org>2024-12-12 17:55:48 -0800
commit81f5d3c6268ff91ee9c36c4cb34f6f9bfd54740d (patch)
treef9f21aa66bd22cfd95ae0c4b8abe57036c8fce0d /src/platform/posix/posix_tcpconn.c
parent371eedeeb6fafe628ae89b9ad2690fa3d6a57e8a (diff)
downloadnng-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/posix/posix_tcpconn.c')
-rw-r--r--src/platform/posix/posix_tcpconn.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/src/platform/posix/posix_tcpconn.c b/src/platform/posix/posix_tcpconn.c
index 74b3371b..ce5243b0 100644
--- a/src/platform/posix/posix_tcpconn.c
+++ b/src/platform/posix/posix_tcpconn.c
@@ -10,6 +10,7 @@
//
#include "core/nng_impl.h"
+#include "platform/posix/posix_pollq.h"
#include <errno.h>
#include <fcntl.h>
@@ -199,16 +200,30 @@ tcp_close(void *arg)
nni_mtx_unlock(&c->mtx);
}
+static void
+tcp_stop(void *arg)
+{
+ nni_tcp_conn *c = arg;
+ nni_posix_pfd *pfd;
+ tcp_close(c);
+
+ nni_mtx_lock(&c->mtx);
+ pfd = c->pfd;
+ c->pfd = NULL;
+ nni_mtx_unlock(&c->mtx);
+
+ if (pfd != NULL) {
+ nni_posix_pfd_fini(pfd);
+ }
+}
+
// tcp_fini may block briefly waiting for the pollq thread.
// To get that out of our context, we simply reap this.
static void
tcp_fini(void *arg)
{
nni_tcp_conn *c = arg;
- tcp_close(c);
- if (c->pfd != NULL) {
- nni_posix_pfd_fini(c->pfd);
- }
+ tcp_stop(c);
nni_mtx_fini(&c->mtx);
if (c->dialer != NULL) {
@@ -221,6 +236,7 @@ static nni_reap_list tcp_reap_list = {
.rl_offset = offsetof(nni_tcp_conn, reap),
.rl_func = tcp_fini,
};
+
static void
tcp_free(void *arg)
{
@@ -454,6 +470,7 @@ nni_posix_tcp_alloc(nni_tcp_conn **cp, nni_tcp_dialer *d)
nni_aio_list_init(&c->writeq);
c->stream.s_free = tcp_free;
+ c->stream.s_stop = tcp_stop;
c->stream.s_close = tcp_close;
c->stream.s_recv = tcp_recv;
c->stream.s_send = tcp_send;