Make logging use a fixed-length buffer to avoid race conditions.

Previously, race conditions occurred inside logging, that caused
segfaults because a thread was trying to use an old pointer that
was freed when the string was reallocated. Using a fixed-length buffer
avoids this, at the cost of cutting too long messages over seveal lines.
This commit is contained in:
Ekdohibs 2016-04-21 10:45:42 +02:00 committed by paramat
parent 5c32c5e945
commit c350cfb50b
1 changed files with 18 additions and 6 deletions

View File

@ -34,9 +34,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <cerrno> #include <cerrno>
#include <cstring> #include <cstring>
const int BUFFER_LENGTH = 256;
class StringBuffer : public std::streambuf { class StringBuffer : public std::streambuf {
public: public:
StringBuffer() {} StringBuffer() {
buffer_index = 0;
}
int overflow(int c); int overflow(int c);
virtual void flush(const std::string &buf) = 0; virtual void flush(const std::string &buf) = 0;
@ -44,7 +48,8 @@ public:
void push_back(char c); void push_back(char c);
private: private:
std::string buffer; char buffer[BUFFER_LENGTH];
int buffer_index;
}; };
@ -338,11 +343,18 @@ std::streamsize StringBuffer::xsputn(const char *s, std::streamsize n)
void StringBuffer::push_back(char c) void StringBuffer::push_back(char c)
{ {
if (c == '\n' || c == '\r') { if (c == '\n' || c == '\r') {
if (!buffer.empty()) if (buffer_index)
flush(buffer); flush(std::string(buffer, buffer_index));
buffer.clear(); buffer_index = 0;
} else { } else {
buffer.push_back(c); int index = buffer_index;
buffer[index++] = c;
if (index >= BUFFER_LENGTH) {
flush(std::string(buffer, buffer_index));
buffer_index = 0;
} else {
buffer_index = index;
}
} }
} }