Expose IsGoogleLoggingInitialized() in public API.

Usually library does not have control of the process lifespan.
Without this function, it is impossible to init/shutdown reliably.
It has been one of the major pain points for years when using glog in libraries.

AFAIK 3 workarounds have been used previously:
1. Init without checking. This causes compatiblity issues with other libs using glog.
2. Also provide a init function in library's API. This makes API complicated and stateful, especially for libs that does not mean to stay for the entire life of process.
3. Steal the utility function in internal namespace. Does not work with msvc (due to missing dllexport) or `gcc -fvisibility=hidden`.

None of them are perfect, except for the last hack that usually works well on Linux.
0.5.0 changes default visibility to hidden and it does not work anymore.

Resolve https://github.com/google/glog/issues/125
This commit is contained in:
Tongliang Liao 2021-05-13 08:24:08 +08:00
parent d5c04eec9e
commit 81e0d616ed
5 changed files with 19 additions and 6 deletions

View File

@ -594,6 +594,9 @@ GOOGLE_GLOG_DLL_DECL void InitGoogleLogging(const char* argv0,
void* prefix_callback_data = NULL);
#endif
// Check if google's logging library has been initialized.
GOOGLE_GLOG_DLL_DECL bool IsGoogleLoggingInitialized();
// Shutdown google's logging library.
GOOGLE_GLOG_DLL_DECL void ShutdownGoogleLogging();

View File

@ -221,11 +221,15 @@ int main(int argc, char **argv) {
LogWithLevels(0, 0, 0, 0); // simulate "before global c-tors"
const string early_stderr = GetCapturedTestStderr();
EXPECT_FALSE(IsGoogleLoggingInitialized());
// Setting a custom prefix generator (it will use the default format so that
// the golden outputs can be reused):
string prefix_attacher_data = "good data";
InitGoogleLogging(argv[0], &PrefixAttacher, static_cast<void*>(&prefix_attacher_data));
EXPECT_TRUE(IsGoogleLoggingInitialized());
RunSpecifiedBenchmarks();
FLAGS_logtostderr = true;
@ -992,8 +996,10 @@ static void TestCustomLoggerDeletionOnShutdown() {
base::SetLogger(GLOG_INFO,
new RecordDeletionLogger(&custom_logger_deleted,
base::GetLogger(GLOG_INFO)));
EXPECT_TRUE(IsGoogleLoggingInitialized());
ShutdownGoogleLogging();
EXPECT_TRUE(custom_logger_deleted);
EXPECT_FALSE(IsGoogleLoggingInitialized());
}
_START_GOOGLE_NAMESPACE_

View File

@ -197,8 +197,12 @@ int main(int argc, char **argv) {
LogWithLevels(0, 0, 0, 0); // simulate "before global c-tors"
const string early_stderr = GetCapturedTestStderr();
EXPECT_FALSE(IsGoogleLoggingInitialized());
InitGoogleLogging(argv[0]);
EXPECT_TRUE(IsGoogleLoggingInitialized());
RunSpecifiedBenchmarks();
FLAGS_logtostderr = true;
@ -965,8 +969,10 @@ static void TestCustomLoggerDeletionOnShutdown() {
base::SetLogger(GLOG_INFO,
new RecordDeletionLogger(&custom_logger_deleted,
base::GetLogger(GLOG_INFO)));
EXPECT_TRUE(IsGoogleLoggingInitialized());
ShutdownGoogleLogging();
EXPECT_TRUE(custom_logger_deleted);
EXPECT_FALSE(IsGoogleLoggingInitialized());
}
_START_GOOGLE_NAMESPACE_

View File

@ -62,6 +62,10 @@ _START_GOOGLE_NAMESPACE_
static const char* g_program_invocation_short_name = NULL;
bool IsGoogleLoggingInitialized() {
return g_program_invocation_short_name != NULL;
}
_END_GOOGLE_NAMESPACE_
// The following APIs are all internal.
@ -176,10 +180,6 @@ const char* ProgramInvocationShortName() {
}
}
bool IsGoogleLoggingInitialized() {
return g_program_invocation_short_name != NULL;
}
#ifdef OS_WINDOWS
struct timeval {
long tv_sec, tv_usec;

View File

@ -163,8 +163,6 @@ namespace glog_internal_namespace_ {
const char* ProgramInvocationShortName();
bool IsGoogleLoggingInitialized();
int64 CycleClock_Now();
int64 UsecToCycles(int64 usec);