#include "utilities.h"
+#include <algorithm>
#include <assert.h>
#include <iomanip>
#include <string>
#define PATH_SEPARATOR '/'
#ifndef HAVE_PREAD
+#if defined(OS_WINDOWS)
+#include <BaseTsd.h>
+#define ssize_t SSIZE_T
+#endif
static ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
off_t orig_offset = lseek(fd, 0, SEEK_CUR);
if (orig_offset == (off_t)-1)
!strcmp(term, "xterm") ||
!strcmp(term, "xterm-color") ||
!strcmp(term, "xterm-256color") ||
+ !strcmp(term, "screen-256color") ||
!strcmp(term, "screen") ||
!strcmp(term, "linux") ||
!strcmp(term, "cygwin");
return (FLAGS_max_log_size > 0 ? FLAGS_max_log_size : 1);
}
+// An arbitrary limit on the length of a single log message. This
+// is so that streaming can be done more efficiently.
+const size_t LogMessage::kMaxLogMessageLen = 30000;
+
struct LogMessage::LogMessageData {
- LogMessageData() {};
+ LogMessageData();
int preserved_errno_; // preserved errno
- char* buf_; // buffer space for non FATAL messages
- char* message_text_; // Complete message text (points to selected buffer)
- LogStream* stream_alloc_;
- LogStream* stream_;
+ // Buffer space; contains complete message text.
+ char message_text_[LogMessage::kMaxLogMessageLen+1];
+ LogStream stream_;
char severity_; // What level is this LogMessage logged at?
int line_; // line number where logging call is.
void (LogMessage::*send_method_)(); // Call this in destructor to send
bool has_been_flushed_; // false => data has not been flushed
bool first_fatal_; // true => this was first fatal msg
- ~LogMessageData();
-
private:
LogMessageData(const LogMessageData&);
void operator=(const LogMessageData&);
} // namespace
-// An arbitrary limit on the length of a single log message. This
-// is so that streaming can be done more efficiently.
-const size_t LogMessage::kMaxLogMessageLen = 30000;
// Static log data space to avoid alloc failures in a LOG(FATAL)
//
static Mutex fatal_msg_lock;
static CrashReason crash_reason;
static bool fatal_msg_exclusive = true;
-static char fatal_msg_buf_exclusive[LogMessage::kMaxLogMessageLen+1];
-static char fatal_msg_buf_shared[LogMessage::kMaxLogMessageLen+1];
-static LogMessage::LogStream fatal_msg_stream_exclusive(
- fatal_msg_buf_exclusive, LogMessage::kMaxLogMessageLen, 0);
-static LogMessage::LogStream fatal_msg_stream_shared(
- fatal_msg_buf_shared, LogMessage::kMaxLogMessageLen, 0);
static LogMessage::LogMessageData fatal_msg_data_exclusive;
static LogMessage::LogMessageData fatal_msg_data_shared;
-LogMessage::LogMessageData::~LogMessageData() {
- delete[] buf_;
- delete stream_alloc_;
+LogMessage::LogMessageData::LogMessageData()
+ : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
int ctr, void (LogMessage::*send_method)())
: allocated_(NULL) {
Init(file, line, severity, send_method);
- data_->stream_->set_ctr(ctr);
+ data_->stream_.set_ctr(ctr);
}
LogMessage::LogMessage(const char* file, int line,
if (severity != GLOG_FATAL || !exit_on_dfatal) {
allocated_ = new LogMessageData();
data_ = allocated_;
- data_->buf_ = new char[kMaxLogMessageLen+1];
- data_->message_text_ = data_->buf_;
- data_->stream_alloc_ =
- new LogStream(data_->message_text_, kMaxLogMessageLen, 0);
- data_->stream_ = data_->stream_alloc_;
data_->first_fatal_ = false;
} else {
MutexLock l(&fatal_msg_lock);
if (fatal_msg_exclusive) {
fatal_msg_exclusive = false;
data_ = &fatal_msg_data_exclusive;
- data_->message_text_ = fatal_msg_buf_exclusive;
- data_->stream_ = &fatal_msg_stream_exclusive;
data_->first_fatal_ = true;
} else {
data_ = &fatal_msg_data_shared;
- data_->message_text_ = fatal_msg_buf_shared;
- data_->stream_ = &fatal_msg_stream_shared;
data_->first_fatal_ = false;
}
- data_->stream_alloc_ = NULL;
}
stream().fill('0');
<< ' '
<< data_->basename_ << ':' << data_->line_ << "] ";
}
- data_->num_prefix_chars_ = data_->stream_->pcount();
+ data_->num_prefix_chars_ = data_->stream_.pcount();
if (!FLAGS_log_backtrace_at.empty()) {
char fileline[128];
}
ostream& LogMessage::stream() {
- return *(data_->stream_);
+ return data_->stream_;
}
// Flush buffered message, called by the destructor, or any other function
if (data_->has_been_flushed_ || data_->severity_ < FLAGS_minloglevel)
return;
- data_->num_chars_to_log_ = data_->stream_->pcount();
+ data_->num_chars_to_log_ = data_->stream_.pcount();
data_->num_chars_to_syslog_ =
data_->num_chars_to_log_ - data_->num_prefix_chars_;
// Copy of first FATAL log message so that we can print it out again
// after all the stack traces. To preserve legacy behavior, we don't
-// use fatal_msg_buf_exclusive.
+// use fatal_msg_data_exclusive.
static time_t fatal_time;
static char fatal_message[256];
glog_internal_namespace_::CrashReason* reason) {
reason->filename = fatal_msg_data_exclusive.fullname_;
reason->line_number = fatal_msg_data_exclusive.line_;
- reason->message = fatal_msg_buf_exclusive +
+ reason->message = fatal_msg_data_exclusive.message_text_ +
fatal_msg_data_exclusive.num_prefix_chars_;
#ifdef HAVE_STACKTRACE
// Retrieve the stack trace, omitting the logging frames that got us here.
#if defined(_DEBUG) && defined(_MSC_VER)
// When debugging on windows, avoid the obnoxious dialog and make
// it possible to continue past a LOG(FATAL) in the debugger
- _asm int 3
+ __debugbreak();
#else
abort();
#endif
ErrnoLogMessage::~ErrnoLogMessage() {
// Don't access errno directly because it may have been altered
// while streaming the message.
- char buf[100];
- posix_strerror_r(preserved_errno(), buf, sizeof(buf));
- stream() << ": " << buf << " [" << preserved_errno() << "]";
+ stream() << ": " << StrError(preserved_errno()) << " ["
+ << preserved_errno() << "]";
}
void FlushLogFiles(LogSeverity min_severity) {
bool ok = pclose(pipe) != -1;
if ( !ok ) {
if ( use_logging ) {
- char buf[100];
- posix_strerror_r(errno, buf, sizeof(buf));
- LOG(ERROR) << "Problems sending mail to " << dest << ": " << buf;
+ LOG(ERROR) << "Problems sending mail to " << dest << ": "
+ << StrError(errno);
} else {
- char buf[100];
- posix_strerror_r(errno, buf, sizeof(buf));
- fprintf(stderr, "Problems sending mail to %s: %s\n", dest, buf);
+ fprintf(stderr, "Problems sending mail to %s: %s\n",
+ dest, StrError(errno).c_str());
}
}
return ok;
}
}
+string StrError(int err) {
+ char buf[100];
+ int rc = posix_strerror_r(err, buf, sizeof(buf));
+ if ((rc < 0) || (buf[0] == '\000')) {
+ snprintf(buf, sizeof(buf), "Error number %d", err);
+ }
+ return buf;
+}
+
LogMessageFatal::LogMessageFatal(const char* file, int line) :
LogMessage(file, line, GLOG_FATAL) {}