Merge "libbase: logging fixes"

This commit is contained in:
Elliott Hughes 2015-08-13 21:10:37 +00:00 committed by Gerrit Code Review
commit 45288223d0
2 changed files with 51 additions and 27 deletions

View file

@ -70,9 +70,14 @@ const char* getprogname() {
static char progname[MAX_PATH] = {}; static char progname[MAX_PATH] = {};
if (first) { if (first) {
// TODO(danalbert): This is a full path on Windows. Just get the basename. CHAR longname[MAX_PATH];
DWORD nchars = GetModuleFileName(nullptr, progname, sizeof(progname)); DWORD nchars = GetModuleFileNameA(nullptr, longname, arraysize(longname));
DCHECK_GT(nchars, 0U); if ((nchars >= arraysize(longname)) || (nchars == 0)) {
// String truncation or some other error.
strcpy(progname, "<unknown>");
} else {
strcpy(progname, basename(longname));
}
first = false; first = false;
} }
@ -82,25 +87,22 @@ const char* getprogname() {
class mutex { class mutex {
public: public:
mutex() { mutex() {
semaphore_ = CreateSemaphore(nullptr, 1, 1, nullptr); InitializeCriticalSection(&critical_section_);
CHECK(semaphore_ != nullptr) << "Failed to create Mutex";
} }
~mutex() { ~mutex() {
CloseHandle(semaphore_); DeleteCriticalSection(&critical_section_);
} }
void lock() { void lock() {
DWORD result = WaitForSingleObject(semaphore_, INFINITE); EnterCriticalSection(&critical_section_);
CHECK_EQ(result, WAIT_OBJECT_0) << GetLastError();
} }
void unlock() { void unlock() {
bool result = ReleaseSemaphore(semaphore_, 1, nullptr); LeaveCriticalSection(&critical_section_);
CHECK(result);
} }
private: private:
HANDLE semaphore_; CRITICAL_SECTION critical_section_;
}; };
template <typename LockT> template <typename LockT>
@ -147,8 +149,9 @@ static const char* ProgramInvocationName() {
void StderrLogger(LogId, LogSeverity severity, const char*, const char* file, void StderrLogger(LogId, LogSeverity severity, const char*, const char* file,
unsigned int line, const char* message) { unsigned int line, const char* message) {
static const char* log_characters = "VDIWEF"; static const char log_characters[] = "VDIWEF";
CHECK_EQ(strlen(log_characters), FATAL + 1U); static_assert(arraysize(log_characters) - 1 == FATAL + 1,
"Mismatch in size of log_characters and values in LogSeverity");
char severity_char = log_characters[severity]; char severity_char = log_characters[severity];
fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n", ProgramInvocationName(), fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n", ProgramInvocationName(),
severity_char, getpid(), gettid(), file, line, message); severity_char, getpid(), gettid(), file, line, message);
@ -197,6 +200,20 @@ void InitLogging(char* argv[], LogFunction&& logger) {
InitLogging(argv); InitLogging(argv);
} }
// TODO: make this public; it's independently useful.
class ErrnoRestorer {
public:
ErrnoRestorer(int saved_errno) : saved_errno_(saved_errno) {
}
~ErrnoRestorer() {
errno = saved_errno_;
}
private:
const int saved_errno_;
};
void InitLogging(char* argv[]) { void InitLogging(char* argv[]) {
if (gInitialized) { if (gInitialized) {
return; return;
@ -257,19 +274,25 @@ void SetLogger(LogFunction&& logger) {
gLogger = std::move(logger); gLogger = std::move(logger);
} }
// We can't use basename(3) because this code runs on the Mac, which doesn't
// have a non-modifying basename.
static const char* GetFileBasename(const char* file) {
const char* last_slash = strrchr(file, '/');
return (last_slash == nullptr) ? file : last_slash + 1;
}
// This indirection greatly reduces the stack impact of having lots of // This indirection greatly reduces the stack impact of having lots of
// checks/logging in a function. // checks/logging in a function.
class LogMessageData { class LogMessageData {
public: public:
LogMessageData(const char* file, unsigned int line, LogId id, LogMessageData(const char* file, unsigned int line, LogId id,
LogSeverity severity, int error) LogSeverity severity, int error, int saved_errno)
: file_(file), : file_(GetFileBasename(file)),
line_number_(line), line_number_(line),
id_(id), id_(id),
severity_(severity), severity_(severity),
error_(error) { error_(error),
const char* last_slash = strrchr(file, '/'); errno_restorer_(saved_errno) {
file = (last_slash == nullptr) ? file : last_slash + 1;
} }
const char* GetFile() const { const char* GetFile() const {
@ -307,13 +330,14 @@ class LogMessageData {
const LogId id_; const LogId id_;
const LogSeverity severity_; const LogSeverity severity_;
const int error_; const int error_;
ErrnoRestorer errno_restorer_;
DISALLOW_COPY_AND_ASSIGN(LogMessageData); DISALLOW_COPY_AND_ASSIGN(LogMessageData);
}; };
LogMessage::LogMessage(const char* file, unsigned int line, LogId id, LogMessage::LogMessage(const char* file, unsigned int line, LogId id,
LogSeverity severity, int error) LogSeverity severity, int error)
: data_(new LogMessageData(file, line, id, severity, error)) { : data_(new LogMessageData(file, line, id, severity, error, errno)) {
} }
LogMessage::~LogMessage() { LogMessage::~LogMessage() {

View file

@ -76,10 +76,10 @@ std::string make_log_pattern(android::base::LogSeverity severity,
const char* message) { const char* message) {
static const char* log_characters = "VDIWEF"; static const char* log_characters = "VDIWEF";
char log_char = log_characters[severity]; char log_char = log_characters[severity];
std::string holder(__FILE__);
return android::base::StringPrintf( return android::base::StringPrintf(
"%c[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+ " __FILE__ "%c[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+ %s:[[:digit:]]+] %s",
":[[:digit:]]+] %s", log_char, basename(&holder[0]), message);
log_char, message);
} }
TEST(logging, LOG) { TEST(logging, LOG) {
@ -100,7 +100,7 @@ TEST(logging, LOG) {
#if !defined(_WIN32) #if !defined(_WIN32)
std::regex message_regex( std::regex message_regex(
make_log_pattern(android::base::WARNING, "foobar")); make_log_pattern(android::base::WARNING, "foobar"));
ASSERT_TRUE(std::regex_search(output, message_regex)); ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
#endif #endif
} }
@ -116,7 +116,7 @@ TEST(logging, LOG) {
#if !defined(_WIN32) #if !defined(_WIN32)
std::regex message_regex( std::regex message_regex(
make_log_pattern(android::base::INFO, "foobar")); make_log_pattern(android::base::INFO, "foobar"));
ASSERT_TRUE(std::regex_search(output, message_regex)); ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
#endif #endif
} }
@ -143,7 +143,7 @@ TEST(logging, LOG) {
#if !defined(_WIN32) #if !defined(_WIN32)
std::regex message_regex( std::regex message_regex(
make_log_pattern(android::base::DEBUG, "foobar")); make_log_pattern(android::base::DEBUG, "foobar"));
ASSERT_TRUE(std::regex_search(output, message_regex)); ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
#endif #endif
} }
} }
@ -162,7 +162,7 @@ TEST(logging, PLOG) {
#if !defined(_WIN32) #if !defined(_WIN32)
std::regex message_regex(make_log_pattern( std::regex message_regex(make_log_pattern(
android::base::INFO, "foobar: No such file or directory")); android::base::INFO, "foobar: No such file or directory"));
ASSERT_TRUE(std::regex_search(output, message_regex)); ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
#endif #endif
} }
} }
@ -183,7 +183,7 @@ TEST(logging, UNIMPLEMENTED) {
android::base::StringPrintf("%s unimplemented ", __PRETTY_FUNCTION__); android::base::StringPrintf("%s unimplemented ", __PRETTY_FUNCTION__);
std::regex message_regex( std::regex message_regex(
make_log_pattern(android::base::ERROR, expected_message.c_str())); make_log_pattern(android::base::ERROR, expected_message.c_str()));
ASSERT_TRUE(std::regex_search(output, message_regex)); ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
#endif #endif
} }
} }