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:
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
......@@ -123,33 +121,70 @@ private:
template<typename CharT>
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 {
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::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.");
return Buffer(newData, retainedLen, true);
}
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);
}
const char* const data;
const size_t len;
const bool isOwned;
std::shared_ptr<char[]> data;
int length;
int isDetached;
};
struct FileBuffer {
......@@ -165,7 +200,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 +241,7 @@ public:
}
Buffer buffer() const {
return Buffer(data_.data(), pptr() - &data_[0]);
return Buffer((char*) data_.data(), pptr() - &data_[0]);
}
void clear() {
......@@ -214,7 +249,7 @@ public:
this->setp(&data_[0], &data_[0] + data_.capacity());
}
protected:
protected:
int_type overflow(int_type ch);
private:
......@@ -261,7 +296,7 @@ public:
return gptr;
}
private:
private:
StreamCursor& cursor;
size_t position;
char *eback;
......
......@@ -79,15 +79,18 @@ private:
struct BufferHolder {
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)
: 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 +104,51 @@ 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:
// virtual ~BufferHolder() {}
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;
// union U {
// Buffer raw;
// Fd fd;
U(Buffer buffer) : raw(buffer) { }
U(Fd fd_) : fd(fd_) { }
} u;
// U(Buffer buffer) : raw(buffer) { }
// U(Fd fd_) : fd(fd_) { }
// ~U() {
// if (this.isRaw()) {}
// }
// } u;
size_t size_= 0;
off_t offset_ = 0;
Type type;
......@@ -225,9 +235,11 @@ private:
std::shared_ptr<Peer>& getPeer(Polling::Tag tag);
void
armTimerMs(Fd fd,
std::chrono::milliseconds value,
Async::Deferred<uint64_t> deferred);
armTimerMs(
Fd fd,
std::chrono::milliseconds value,
Async::Deferred<uint64_t> deferred
);
void armTimerMsImpl(TimerEntry entry);
......
......@@ -195,8 +195,8 @@ Transport::handlePeerDisconnection(const std::shared_ptr<Peer>& peer) {
auto & entry = wq.front();
const BufferHolder & buffer = entry.buffer;
if (buffer.isRaw()) {
auto raw = buffer.raw();
if (raw.isOwned) delete[] raw.data;
// auto raw = buffer.raw();
// if (raw.isOwned) delete[] raw.data;
}
wq.pop_front();
}
......@@ -224,13 +224,13 @@ 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;
//auto raw = buffer.raw();
// if (raw.isOwned) delete[] raw.data;
}
wq.pop_front();
if (wq.size() == 0) {
......@@ -247,7 +247,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