Commit edd003b6 authored by Max Kellermann's avatar Max Kellermann

lib/nfs/Connection: fix memory leak when cancelling Open()

Close the newly allocated file handle passed to the callback.
parent 10cc87e4
...@@ -94,6 +94,14 @@ NfsConnection::CancellableCallback::Callback(int err, void *data) ...@@ -94,6 +94,14 @@ NfsConnection::CancellableCallback::Callback(int err, void *data)
cb.OnNfsError(Error(nfs_domain, err, cb.OnNfsError(Error(nfs_domain, err,
(const char *)data)); (const char *)data));
} else { } else {
if (open) {
/* a nfs_open_async() call was cancelled - to
avoid a memory leak, close the newly
allocated file handle immediately */
struct nfsfh *fh = (struct nfsfh *)data;
connection.Close(fh);
}
connection.callbacks.Remove(*this); connection.callbacks.Remove(*this);
} }
} }
...@@ -157,7 +165,7 @@ NfsConnection::Open(const char *path, int flags, NfsCallback &callback, ...@@ -157,7 +165,7 @@ NfsConnection::Open(const char *path, int flags, NfsCallback &callback,
{ {
assert(!callbacks.Contains(callback)); assert(!callbacks.Contains(callback));
auto &c = callbacks.Add(callback, *this); auto &c = callbacks.Add(callback, *this, true);
if (!c.Open(context, path, flags, error)) { if (!c.Open(context, path, flags, error)) {
callbacks.Remove(c); callbacks.Remove(c);
return false; return false;
...@@ -172,7 +180,7 @@ NfsConnection::Stat(struct nfsfh *fh, NfsCallback &callback, Error &error) ...@@ -172,7 +180,7 @@ NfsConnection::Stat(struct nfsfh *fh, NfsCallback &callback, Error &error)
{ {
assert(!callbacks.Contains(callback)); assert(!callbacks.Contains(callback));
auto &c = callbacks.Add(callback, *this); auto &c = callbacks.Add(callback, *this, false);
if (!c.Stat(context, fh, error)) { if (!c.Stat(context, fh, error)) {
callbacks.Remove(c); callbacks.Remove(c);
return false; return false;
...@@ -188,7 +196,7 @@ NfsConnection::Read(struct nfsfh *fh, uint64_t offset, size_t size, ...@@ -188,7 +196,7 @@ NfsConnection::Read(struct nfsfh *fh, uint64_t offset, size_t size,
{ {
assert(!callbacks.Contains(callback)); assert(!callbacks.Contains(callback));
auto &c = callbacks.Add(callback, *this); auto &c = callbacks.Add(callback, *this, false);
if (!c.Read(context, fh, offset, size, error)) { if (!c.Read(context, fh, offset, size, error)) {
callbacks.Remove(c); callbacks.Remove(c);
return false; return false;
......
...@@ -39,11 +39,21 @@ class NfsConnection : SocketMonitor, DeferredMonitor { ...@@ -39,11 +39,21 @@ class NfsConnection : SocketMonitor, DeferredMonitor {
class CancellableCallback : public CancellablePointer<NfsCallback> { class CancellableCallback : public CancellablePointer<NfsCallback> {
NfsConnection &connection; NfsConnection &connection;
/**
* Is this a nfs_open_async() operation? If yes, then
* we need to call nfs_close_async() on the new file
* handle as soon as the callback is invoked
* successfully.
*/
const bool open;
public: public:
explicit CancellableCallback(NfsCallback &_callback, explicit CancellableCallback(NfsCallback &_callback,
NfsConnection &_connection) NfsConnection &_connection,
bool _open)
:CancellablePointer<NfsCallback>(_callback), :CancellablePointer<NfsCallback>(_callback),
connection(_connection) {} connection(_connection),
open(_open) {}
bool Open(nfs_context *context, const char *path, int flags, bool Open(nfs_context *context, const char *path, int flags,
Error &error); Error &error);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment