Merge "libbase: logging fixes"
This commit is contained in:
commit
45288223d0
2 changed files with 51 additions and 27 deletions
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue