Release the e1inp_line when the signalling link is destroyed. The e1inp_line was leaked on every OML/RSL disconnect.
The leak occured on the following call path. e1inp_close_socket ipaccess_close e1inp_sign_link_destroy ipaccess_drop_oml ipaccess_drop handle_ts1_read ipaccess_fd_cb --- src/e1_input.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/src/e1_input.c b/src/e1_input.c index 957b74c..a85dd91 100644 --- a/src/e1_input.c +++ b/src/e1_input.c @@ -486,6 +486,7 @@ void e1inp_sign_link_destroy(struct e1inp_sign_link *link) if (link->ts->line->driver->close) link->ts->line->driver->close(link);
+ e1inp_line_put(link->ts->line); talloc_free(link); }
Hi Holger,
On Mon, Aug 20, 2012 at 03:14:29PM +0200, Holger Hans Peter Freyther wrote:
Release the e1inp_line when the signalling link is destroyed. The e1inp_line was leaked on every OML/RSL disconnect.
The leak occured on the following call path. e1inp_close_socket ipaccess_close e1inp_sign_link_destroy ipaccess_drop_oml ipaccess_drop handle_ts1_read ipaccess_fd_cb
src/e1_input.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/src/e1_input.c b/src/e1_input.c index 957b74c..a85dd91 100644 --- a/src/e1_input.c +++ b/src/e1_input.c @@ -486,6 +486,7 @@ void e1inp_sign_link_destroy(struct e1inp_sign_link *link) if (link->ts->line->driver->close) link->ts->line->driver->close(link);
- e1inp_line_put(link->ts->line); talloc_free(link);
Good catch. If you want to fix it like that, I think that you also need to add the following chunk below:
diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c index 76d1994..3185bc0 100644 --- a/src/input/ipaccess.c +++ b/src/input/ipaccess.c @@ -249,9 +249,6 @@ static int ipaccess_drop(struct osmo_fd *bfd) bfd->fd = -1; ret = -ENOENT; } - /* put the virtual E1 line that we cloned for this socket, if - * it becomes unused, it gets released. */ - e1inp_line_put(line); return ret; }
IIRC, the refcnt becomes 2 if both the OML and RSL links are up.
ipaccess_drop calls line->ops->sign_link_down(line), which usually call e1inp_sign_link_destroy twice (one for the RSL link, and one for the OML link).
With your patch, the refcount becomes zero after the two e1inp_sign_link_destroy calls that happen in ->sign_link_down. Thus, releasing the line that we were leaking.
Still, if you don't remove that e1inp_line_put in ipaccess_drop, you hit an access-after-release since e1inp_line_put takes an already released line.
But let me check this tomorrow again after some sleeping :-).
On Tue, Aug 21, 2012 at 03:10:32AM +0200, Pablo Neira Ayuso wrote:
Hi Holger,
Hi Pablo,
IIRC, the refcnt becomes 2 if both the OML and RSL links are up.
hehe, not really sure. The _rsl_cb will will clone the e1inp_line but I think after we know which BTS is making the connection we throw away the cloned line and _get_line the OML one.
With your patch, the refcount becomes zero after the two e1inp_sign_link_destroy calls that happen in ->sign_link_down. Thus, releasing the line that we were leaking.
Sounds plausible. Luckily you only free the link when it becomes 0 (and not smaller). I am going to add an assertion for >= 0 for the refcount.
But let me check this tomorrow again after some sleeping :-).
thanks
On Tue, Aug 21, 2012 at 09:20:54AM +0200, Holger Hans Peter Freyther wrote:
On Tue, Aug 21, 2012 at 03:10:32AM +0200, Pablo Neira Ayuso wrote:
Hi Holger,
Hi Pablo,
IIRC, the refcnt becomes 2 if both the OML and RSL links are up.
hehe, not really sure. The _rsl_cb will will clone the e1inp_line but I think after we know which BTS is making the connection we throw away the cloned line and _get_line the OML one.
With your patch, the refcount becomes zero after the two e1inp_sign_link_destroy calls that happen in ->sign_link_down. Thus, releasing the line that we were leaking.
Sounds plausible. Luckily you only free the link when it becomes 0 (and not smaller). I am going to add an assertion for >= 0 for the refcount.
Hm, I'm looking again at the last patch I sent and it's not correct either.
If we call ipaccess_drop, all signalling links are released since e1inp_sign_link_destroy destroys all sockets (it calls ipaccess_close).
So, your patch is almost right. We have to e1inp_line_put in e1inp_sign_link_destroy. But we have to remove e1inp_line_put in the ipaccess and hsl drivers.
I'll resend a patch for this.