Fixed buffer memory leaks described in...

Fixed buffer memory leaks described in https://github.com/oktal/pistache/issues/399\#issuecomment-459224155
parent 6f7a459b
...@@ -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
...@@ -123,33 +121,70 @@ private: ...@@ -123,33 +121,70 @@ private:
template<typename CharT> template<typename CharT>
size_t ArrayStreamBuf<CharT>::maxSize = Const::DefaultMaxPayload; size_t ArrayStreamBuf<CharT>::maxSize = Const::DefaultMaxPayload;
// struct Buffer {
// Buffer()
// : data(nullptr)
// , len(0)
// , isOwned(false)
// , isDetached(false)
// { }
// Buffer(char * _data, size_t _len, bool _own = false, bool _detached = false)
// : data(_data)
// , len(_len)
// , isOwned(_own)
// , isDetached(_detached)
// { }
// virtual ~Buffer() {
// if (isOwned != false && data != nullptr) {
// delete[] data;
// }
// }
// Buffer detach(size_t fromIndex = 0) const {
// if (fromIndex > len)
// throw std::invalid_argument("Invalid index (> len)");
// size_t retainedLen = len - fromIndex;
// char *newData = new char[retainedLen+1]();
// std::copy(data + fromIndex, data + len, newData);
// return Buffer(newData, retainedLen, true, true);
// }
// char* data = nullptr;
// const size_t len = 0;
// const bool isOwned = false;
// const bool isDetached = false;
// };
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::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.");
auto newDatalength = length - fromIndex;
auto newData = std::shared_ptr<char[]>(new char[newDatalength + 1]());
std::copy(data.get() + fromIndex, data.get() + length, newData.get());
return Buffer(newData, newDatalength, true);
return Buffer(newData, retainedLen, true);
} }
const char* const data; std::shared_ptr<char[]> data;
const size_t len; int length;
const bool isOwned; int isDetached;
}; };
struct FileBuffer { struct FileBuffer {
...@@ -165,7 +200,7 @@ struct FileBuffer { ...@@ -165,7 +200,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 +241,7 @@ public: ...@@ -206,7 +241,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 +249,7 @@ public: ...@@ -214,7 +249,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:
......
...@@ -79,15 +79,18 @@ private: ...@@ -79,15 +79,18 @@ private:
struct BufferHolder { struct BufferHolder {
enum Type { Raw, File }; enum Type { Raw, File };
// explicit BufferHolder(const BufferHolder &buffer, off_t offset = 0)
// : u(buffer), size_(buffer.len), offset_(offset), type(Raw) {}
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 +104,51 @@ private: ...@@ -101,44 +104,51 @@ 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);
} }
// virtual ~BufferHolder() {}
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;
// union U {
U(Buffer buffer) : raw(buffer) { } // Buffer raw;
U(Fd fd_) : fd(fd_) { } // Fd fd;
} u;
// U(Buffer buffer) : raw(buffer) { }
// U(Fd fd_) : fd(fd_) { }
// ~U() {
// if (this.isRaw()) {}
// }
// } u;
size_t size_= 0; size_t size_= 0;
off_t offset_ = 0; off_t offset_ = 0;
Type type; Type type;
...@@ -225,9 +235,11 @@ private: ...@@ -225,9 +235,11 @@ private:
std::shared_ptr<Peer>& getPeer(Polling::Tag tag); std::shared_ptr<Peer>& getPeer(Polling::Tag tag);
void void
armTimerMs(Fd fd, armTimerMs(
Fd fd,
std::chrono::milliseconds value, std::chrono::milliseconds value,
Async::Deferred<uint64_t> deferred); Async::Deferred<uint64_t> deferred
);
void armTimerMsImpl(TimerEntry entry); void armTimerMsImpl(TimerEntry entry);
......
...@@ -195,8 +195,8 @@ Transport::handlePeerDisconnection(const std::shared_ptr<Peer>& peer) { ...@@ -195,8 +195,8 @@ Transport::handlePeerDisconnection(const std::shared_ptr<Peer>& peer) {
auto & entry = wq.front(); auto & entry = wq.front();
const BufferHolder & buffer = entry.buffer; const BufferHolder & buffer = entry.buffer;
if (buffer.isRaw()) { if (buffer.isRaw()) {
auto raw = buffer.raw(); // auto raw = buffer.raw();
if (raw.isOwned) delete[] raw.data; // if (raw.isOwned) delete[] raw.data;
} }
wq.pop_front(); wq.pop_front();
} }
...@@ -224,13 +224,13 @@ Transport::asyncWriteImpl(Fd fd) ...@@ -224,13 +224,13 @@ 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()) { if (buffer.isRaw()) {
auto raw = buffer.raw(); //auto raw = buffer.raw();
if (raw.isOwned) delete[] raw.data; // if (raw.isOwned) delete[] raw.data;
} }
wq.pop_front(); wq.pop_front();
if (wq.size() == 0) { if (wq.size() == 0) {
...@@ -247,7 +247,7 @@ Transport::asyncWriteImpl(Fd fd) ...@@ -247,7 +247,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