From 5eb73201f7e7d5e2cd9fe0f7927077d1bc0f0c53 Mon Sep 17 00:00:00 2001 From: Bill Williams Date: Mon, 22 May 2017 10:17:41 -0700 Subject: clean fix of memory leak in btcp.c when nn_bind returns EADDRINUSE --- src/aio/fsm.c | 10 ++++++++++ src/aio/fsm.h | 4 ++++ src/transports/tcp/btcp.c | 15 ++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/aio/fsm.c b/src/aio/fsm.c index 33250de..54ec60b 100644 --- a/src/aio/fsm.c +++ b/src/aio/fsm.c @@ -178,6 +178,16 @@ void nn_fsm_action (struct nn_fsm *self, int type) nn_fsm_feed (self, NN_FSM_ACTION, type, NULL); } +void nn_fsm_raise_from_src (struct nn_fsm *self, struct nn_fsm_event *event, + int src, int type) +{ + event->fsm = self; + event->src = src; + event->srcptr = self->srcptr; + event->type = type; + nn_ctx_raise (self->ctx, event); +} + void nn_fsm_raise (struct nn_fsm *self, struct nn_fsm_event *event, int type) { event->fsm = self->owner; diff --git a/src/aio/fsm.h b/src/aio/fsm.h index 19eca1a..5a41aef 100644 --- a/src/aio/fsm.h +++ b/src/aio/fsm.h @@ -96,6 +96,10 @@ struct nn_worker *nn_fsm_choose_worker (struct nn_fsm *self); /* Using this function state machine can trigger an action on itself. */ void nn_fsm_action (struct nn_fsm *self, int type); +/* Send event from the state machine to its owner. */ +void nn_fsm_raise_from_src (struct nn_fsm *self, struct nn_fsm_event *event, + int src, int type); + /* Send event from the state machine to its owner. */ void nn_fsm_raise (struct nn_fsm *self, struct nn_fsm_event *event, int type); diff --git a/src/transports/tcp/btcp.c b/src/transports/tcp/btcp.c index 4fe8b58..1fdef03 100644 --- a/src/transports/tcp/btcp.c +++ b/src/transports/tcp/btcp.c @@ -59,11 +59,16 @@ #define NN_BTCP_SRC_USOCK 1 #define NN_BTCP_SRC_ATCP 2 +#define NN_BTCP_SRC_BTCP 3 + +#define NN_BTCP_TYPE_LISTEN_ERR 1 + struct nn_btcp { /* The state machine. */ struct nn_fsm fsm; + struct nn_fsm_event listen_error; int state; struct nn_ep *ep; @@ -143,6 +148,7 @@ int nn_btcp_create (struct nn_ep *ep) /* Initialise the structure. */ nn_fsm_init_root (&self->fsm, nn_btcp_handler, nn_btcp_shutdown, nn_ep_getctx (ep)); + nn_fsm_event_init (&self->listen_error); self->state = NN_BTCP_STATE_IDLE; self->atcp = NULL; nn_list_init (&self->atcps); @@ -154,7 +160,8 @@ int nn_btcp_create (struct nn_ep *ep) rc = nn_btcp_listen (self); if (rc != 0) { - // I suspect we might need to do nn_free here. + nn_fsm_raise_from_src (&self->fsm, &self->listen_error, + NN_BTCP_SRC_BTCP, NN_BTCP_TYPE_LISTEN_ERR); return rc; } @@ -267,6 +274,12 @@ static void nn_btcp_handler (struct nn_fsm *self, int src, int type, /* The execution is yielded to the atcp state machine in this state. */ /******************************************************************************/ case NN_BTCP_STATE_ACTIVE: + if (src == NN_BTCP_SRC_BTCP) { + nn_assert (type == NN_BTCP_TYPE_LISTEN_ERR); + nn_free (btcp); + return; + } + if (src == NN_BTCP_SRC_USOCK) { /* usock object cleaning up */ nn_assert (type == NN_USOCK_SHUTDOWN || type == NN_USOCK_STOPPED); -- cgit v1.2.1