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