Unverified Commit 2fdbe570 authored by Dennis Jenkins's avatar Dennis Jenkins Committed by GitHub

Merge pull request #435 from arthurafarias/arthurafarias-fix-buffer-memory-leak

Fix buffer memory leak
parents d2e6e6d2 916c5f2c
...@@ -60,7 +60,6 @@ public: ...@@ -60,7 +60,6 @@ public:
const CharT* gptr = this->gptr(); const CharT* gptr = this->gptr();
return *(gptr + 1); return *(gptr + 1);
} }
}; };
template<typename CharT = char> template<typename CharT = char>
...@@ -74,7 +73,6 @@ public: ...@@ -74,7 +73,6 @@ public:
RawStreamBuf(char* begin, size_t len) { RawStreamBuf(char* begin, size_t len) {
Base::setg(begin, begin, begin + len); Base::setg(begin, begin, begin + len);
} }
}; };
// Make the buffer dynamic // Make the buffer dynamic
...@@ -124,32 +122,32 @@ template<typename CharT> ...@@ -124,32 +122,32 @@ template<typename CharT>
size_t ArrayStreamBuf<CharT>::maxSize = Const::DefaultMaxPayload; size_t ArrayStreamBuf<CharT>::maxSize = Const::DefaultMaxPayload;
struct Buffer { struct Buffer {
Buffer()
: data(nullptr)
, len(0)
, isOwned(false)
{ }
Buffer(const char * const _data, size_t _len, bool _own = false) Buffer() : data(nullptr), length(0), isDetached(false) {}
: data(_data) Buffer(std::shared_ptr<char> _data, int _length, bool _isDetached = false) : data(_data), length(_length), isDetached(_isDetached) {}
, len(_len) Buffer(const char * _data, int _length, bool _isDetached = false) : data(nullptr), length(_length), isDetached(_isDetached) {
, isOwned(_own) data = std::shared_ptr<char>(new char[_length+1](), std::default_delete<char[]>());
{ } std::copy(_data, _data + _length + 1, data.get());
}
Buffer detach(size_t fromIndex = 0) const { Buffer detach(int fromIndex){
if (fromIndex > len)
throw std::invalid_argument("Invalid index (> len)");
size_t retainedLen = len - fromIndex; if (!data) Buffer();
char *newData = new char[retainedLen]; if (length < fromIndex)
std::copy(data + fromIndex, data + len, newData); throw std::range_error("Trying to detach buffer from an index bigger than lengthght.");
return Buffer(newData, retainedLen, true); auto newDatalength = length - fromIndex;
} auto newData = std::shared_ptr<char>(new char[newDatalength + 1](), std::default_delete<char[]>());
std::copy(data.get() + fromIndex, data.get() + length, newData.get());
return Buffer(newData, newDatalength, true);
}
std::shared_ptr<char> data;
int length;
int isDetached;
const char* const data;
const size_t len;
const bool isOwned;
}; };
struct FileBuffer { struct FileBuffer {
...@@ -165,7 +163,7 @@ struct FileBuffer { ...@@ -165,7 +163,7 @@ struct FileBuffer {
Fd fd() const { return fd_; } Fd fd() const { return fd_; }
size_t size() const { return size_; } size_t size() const { return size_; }
private: private:
std::string fileName_; std::string fileName_;
Fd fd_; Fd fd_;
size_t size_; size_t size_;
...@@ -206,7 +204,7 @@ public: ...@@ -206,7 +204,7 @@ public:
} }
Buffer buffer() const { Buffer buffer() const {
return Buffer(data_.data(), pptr() - &data_[0]); return Buffer((char*) data_.data(), pptr() - &data_[0]);
} }
void clear() { void clear() {
...@@ -214,7 +212,7 @@ public: ...@@ -214,7 +212,7 @@ public:
this->setp(&data_[0], &data_[0] + data_.capacity()); this->setp(&data_[0], &data_[0] + data_.capacity());
} }
protected: protected:
int_type overflow(int_type ch); int_type overflow(int_type ch);
private: private:
...@@ -261,7 +259,7 @@ public: ...@@ -261,7 +259,7 @@ public:
return gptr; return gptr;
} }
private: private:
StreamCursor& cursor; StreamCursor& cursor;
size_t position; size_t position;
char *eback; char *eback;
......
...@@ -80,14 +80,14 @@ private: ...@@ -80,14 +80,14 @@ private:
enum Type { Raw, File }; enum Type { Raw, File };
explicit BufferHolder(const Buffer& buffer, off_t offset = 0) explicit BufferHolder(const Buffer& buffer, off_t offset = 0)
: u(buffer) : _raw(buffer)
, size_(buffer.len) , size_(buffer.length)
, offset_(offset) , offset_(offset)
, type(Raw) , type(Raw)
{ } { }
explicit BufferHolder(const FileBuffer& buffer, off_t offset = 0) explicit BufferHolder(const FileBuffer& buffer, off_t offset = 0)
: u(buffer.fd()) : _fd(buffer.fd())
, size_(buffer.size()) , size_(buffer.size())
, offset_(offset) , offset_(offset)
, type(File) , type(File)
...@@ -101,44 +101,38 @@ private: ...@@ -101,44 +101,38 @@ private:
Fd fd() const { Fd fd() const {
if (!isFile()) if (!isFile())
throw std::runtime_error("Tried to retrieve fd of a non-filebuffer"); throw std::runtime_error("Tried to retrieve fd of a non-filebuffer");
return _fd;
return u.fd;
} }
Buffer raw() const { Buffer raw() const {
if (!isRaw()) if (!isRaw())
throw std::runtime_error("Tried to retrieve raw data of a non-buffer"); throw std::runtime_error("Tried to retrieve raw data of a non-buffer");
return _raw;
return u.raw;
} }
BufferHolder detach(size_t offset = 0) const { BufferHolder detach(size_t offset = 0) {
if (!isRaw()) if (!isRaw())
return BufferHolder(u.fd, size_, offset); return BufferHolder(_fd, size_, offset);
if (u.raw.isOwned) if (_raw.isDetached)
return BufferHolder(u.raw, offset); return BufferHolder(_raw, offset);
auto detached = u.raw.detach(offset); auto detached = _raw.detach(offset);
return BufferHolder(detached); return BufferHolder(detached);
} }
private: private:
BufferHolder(Fd fd, size_t size, off_t offset = 0) BufferHolder(Fd fd, size_t size, off_t offset = 0)
: u(fd) : _fd(fd)
, size_(size) , size_(size)
, offset_(offset) , offset_(offset)
, type(File) , type(File)
{ } { }
union U { Buffer _raw;
Buffer raw; Fd _fd;
Fd fd;
U(Buffer buffer) : raw(buffer) { }
U(Fd fd_) : fd(fd_) { }
} u;
size_t size_= 0; size_t size_= 0;
off_t offset_ = 0; off_t offset_ = 0;
Type type; Type type;
...@@ -225,9 +219,11 @@ private: ...@@ -225,9 +219,11 @@ private:
std::shared_ptr<Peer>& getPeer(Polling::Tag tag); std::shared_ptr<Peer>& getPeer(Polling::Tag tag);
void void
armTimerMs(Fd fd, armTimerMs(
std::chrono::milliseconds value, Fd fd,
Async::Deferred<uint64_t> deferred); std::chrono::milliseconds value,
Async::Deferred<uint64_t> deferred
);
void armTimerMsImpl(TimerEntry entry); void armTimerMsImpl(TimerEntry entry);
......
...@@ -192,12 +192,6 @@ Transport::handlePeerDisconnection(const std::shared_ptr<Peer>& peer) { ...@@ -192,12 +192,6 @@ Transport::handlePeerDisconnection(const std::shared_ptr<Peer>& peer) {
Guard guard(toWriteLock); Guard guard(toWriteLock);
auto & wq = toWrite[fd]; auto & wq = toWrite[fd];
while (wq.size() > 0) { while (wq.size() > 0) {
auto & entry = wq.front();
const BufferHolder & buffer = entry.buffer;
if (buffer.isRaw()) {
auto raw = buffer.raw();
if (raw.isOwned) delete[] raw.data;
}
wq.pop_front(); wq.pop_front();
} }
toWrite.erase(fd); toWrite.erase(fd);
...@@ -224,14 +218,10 @@ Transport::asyncWriteImpl(Fd fd) ...@@ -224,14 +218,10 @@ Transport::asyncWriteImpl(Fd fd)
auto & entry = wq.front(); auto & entry = wq.front();
int flags = entry.flags; int flags = entry.flags;
const BufferHolder &buffer = entry.buffer; BufferHolder &buffer = entry.buffer;
Async::Deferred<ssize_t> deferred = std::move(entry.deferred); Async::Deferred<ssize_t> deferred = std::move(entry.deferred);
auto cleanUp = [&]() { auto cleanUp = [&]() {
if (buffer.isRaw()) {
auto raw = buffer.raw();
if (raw.isOwned) delete[] raw.data;
}
wq.pop_front(); wq.pop_front();
if (wq.size() == 0) { if (wq.size() == 0) {
toWrite.erase(fd); toWrite.erase(fd);
...@@ -247,7 +237,7 @@ Transport::asyncWriteImpl(Fd fd) ...@@ -247,7 +237,7 @@ Transport::asyncWriteImpl(Fd fd)
if (buffer.isRaw()) { if (buffer.isRaw()) {
auto raw = buffer.raw(); auto raw = buffer.raw();
auto ptr = raw.data + totalWritten; auto ptr = raw.data.get() + totalWritten;
#ifdef PISTACHE_USE_SSL #ifdef PISTACHE_USE_SSL
auto it = peers.find(fd); auto it = peers.find(fd);
......
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