From a543627abd19f321ddd4259e222e6437e8312417 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sun, 14 Dec 2014 15:56:53 +0100 Subject: lib/nfs/Connection: fix memory leak (and assertion failure) nfs_destroy_context() will invoke all pending callbacks with err==-EINTR. In CancellableCallback::Callback(), this will invoke NfsConnection::DeferClose(), which however is only designed to be called from nfs_service(). In non-debug mode, this will leak memory because nfs_close_async() is never called. Workaround: before nfs_destroy_context(), invoke nfs_close_async() on all pending file handles. --- src/lib/nfs/Connection.cxx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/lib/nfs/Connection.cxx') diff --git a/src/lib/nfs/Connection.cxx b/src/lib/nfs/Connection.cxx index 48db620be..83b388dc4 100644 --- a/src/lib/nfs/Connection.cxx +++ b/src/lib/nfs/Connection.cxx @@ -132,6 +132,17 @@ NfsConnection::CancellableCallback::CancelAndScheduleClose(struct nfsfh *fh) Cancel(); } +inline void +NfsConnection::CancellableCallback::PrepareDestroyContext() +{ + assert(IsCancelled()); + + if (close_fh != nullptr) { + connection.InternalClose(close_fh); + close_fh = nullptr; + } +} + inline void NfsConnection::CancellableCallback::Callback(int err, void *data) { @@ -370,6 +381,10 @@ NfsConnection::DestroyContext() if (SocketMonitor::IsDefined()) SocketMonitor::Cancel(); + callbacks.ForEach([](CancellableCallback &c){ + c.PrepareDestroyContext(); + }); + nfs_destroy_context(context); context = nullptr; } -- cgit v1.2.3