Skip to content

Commit

Permalink
Allow updating vmodule levels after vmodule was parsed, invalidate al…
Browse files Browse the repository at this point in the history
…ready cached site flags

vmodule flag is relevant for GNUC environments only.
  • Loading branch information
romange committed May 23, 2021
1 parent fef48c1 commit 86fea1a
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 7 deletions.
15 changes: 11 additions & 4 deletions src/glog/vlog_is_on.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@
// parsing of --vmodule flag and/or SetVLOGLevel calls.
#define VLOG_IS_ON(verboselevel) \
__extension__ \
({ static @ac_google_namespace@::int32* vlocal__ = NULL; \
({ static @ac_google_namespace@::SiteFlag vlocal__{NULL, NULL, 0, NULL}; \
@ac_google_namespace@::int32 verbose_level__ = (verboselevel); \
(vlocal__ == NULL ? @ac_google_namespace@::InitVLOG3__(&vlocal__, &FLAGS_v, \
__FILE__, verbose_level__) : *vlocal__ >= verbose_level__); \
(vlocal__.level == NULL ? @ac_google_namespace@::InitVLOG3__(&vlocal__, &FLAGS_v, \
__FILE__, verbose_level__) : *vlocal__.level >= verbose_level__); \
})
#else
// GNU extensions not available, so we do not support --vmodule.
Expand All @@ -105,6 +105,13 @@ extern GOOGLE_GLOG_DLL_DECL int SetVLOGLevel(const char* module_pattern,

// Various declarations needed for VLOG_IS_ON above: =========================

struct SiteFlag {
@ac_google_namespace@::int32* level;
const char* base_name;
size_t base_len;
SiteFlag* next;
};

// Helper routine which determines the logging info for a particalur VLOG site.
// site_flag is the address of the site-local pointer to the controlling
// verbosity level
Expand All @@ -114,7 +121,7 @@ extern GOOGLE_GLOG_DLL_DECL int SetVLOGLevel(const char* module_pattern,
// We will return the return value for VLOG_IS_ON
// and if possible set *site_flag appropriately.
extern GOOGLE_GLOG_DLL_DECL bool InitVLOG3__(
@ac_google_namespace@::int32** site_flag,
@ac_google_namespace@::SiteFlag* site_flag,
@ac_google_namespace@::int32* site_default,
const char* fname,
@ac_google_namespace@::int32 verbose_level);
Expand Down
20 changes: 20 additions & 0 deletions src/logging_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ static void TestLogging(bool check_counts);
static void TestRawLogging();
static void LogWithLevels(int v, int severity, bool err, bool alsoerr);
static void TestLoggingLevels();
static void TestVLogModule();
static void TestLogString();
static void TestLogSink();
static void TestLogToString();
Expand Down Expand Up @@ -223,6 +224,7 @@ int main(int argc, char **argv) {
TestLogging(true);
TestRawLogging();
TestLoggingLevels();
TestVLogModule();
TestLogString();
TestLogSink();
TestLogToString();
Expand Down Expand Up @@ -453,6 +455,24 @@ void TestLoggingLevels() {
LogWithLevels(1, GLOG_FATAL, false, true);
}

int TestVlogHelper() {
if (VLOG_IS_ON(1)) {
return 1;
}
return 0;
}

void TestVLogModule() {
int c = TestVlogHelper();
EXPECT_EQ(0, c);

#if defined(__GNUC__)
EXPECT_EQ(0, SetVLOGLevel("logging_unittest", 1));
c = TestVlogHelper();
EXPECT_EQ(1, c);
#endif
}

TEST(DeathRawCHECK, logging) {
ASSERT_DEATH(RAW_CHECK(false, "failure 1"),
"RAW: Check false failed: failure 1");
Expand Down
45 changes: 42 additions & 3 deletions src/vlog_is_on.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ static Mutex vmodule_lock;
// Pointer to head of the VModuleInfo list.
// It's a map from module pattern to logging level for those module(s).
static VModuleInfo* vmodule_list = 0;
static SiteFlag* cached_site_list = 0;

// Boolean initialization flag.
static bool inited_vmodule = false;

Expand Down Expand Up @@ -190,6 +192,23 @@ int SetVLOGLevel(const char* module_pattern, int log_level) {
info->vlog_level = log_level;
info->next = vmodule_list;
vmodule_list = info;

SiteFlag** item_ptr = &cached_site_list;
SiteFlag* item = cached_site_list;

// We traverse the list fully because the pattern can match several items
// from the list.
while (item) {
if (SafeFNMatch_(module_pattern, pattern_len, item->base_name,
item->base_len)) {
// Redirect the cached value to its module override.
item->level = &info->vlog_level;
*item_ptr = item->next; // Remove the item from the list.
} else {
item_ptr = &item->next;
}
item = *item_ptr;
}
}
}
RAW_VLOG(1, "Set VLOG level for \"%s\" to %d", module_pattern, log_level);
Expand All @@ -198,7 +217,7 @@ int SetVLOGLevel(const char* module_pattern, int log_level) {

// NOTE: Individual VLOG statements cache the integer log level pointers.
// NOTE: This function must not allocate memory or require any locks.
bool InitVLOG3__(int32** site_flag, int32* site_default,
bool InitVLOG3__(SiteFlag* site_flag, int32* level_default,
const char* fname, int32 verbose_level) {
MutexLock l(&vmodule_lock);
bool read_vmodule_flag = inited_vmodule;
Expand All @@ -211,10 +230,17 @@ bool InitVLOG3__(int32** site_flag, int32* site_default,
int old_errno = errno;

// site_default normally points to FLAGS_v
int32* site_flag_value = site_default;
int32* site_flag_value = level_default;

// Get basename for file
const char* base = strrchr(fname, '/');

#ifdef _WIN32
if (!base) {
base = strrchr(fname, '\\');
}
#endif

base = base ? (base+1) : fname;
const char* base_end = strchr(base, '.');
size_t base_length = base_end ? size_t(base_end - base) : strlen(base);
Expand Down Expand Up @@ -244,7 +270,20 @@ bool InitVLOG3__(int32** site_flag, int32* site_default,
ANNOTATE_BENIGN_RACE(site_flag,
"*site_flag may be written by several threads,"
" but the value will be the same");
if (read_vmodule_flag) *site_flag = site_flag_value;
if (read_vmodule_flag) {
site_flag->level = site_flag_value;
// If VLOG flag has been cached to the default site pointer,
// we want to add to the cached list in order to invalidate in case
// SetVModule is called afterwards with new modules.
// The performance penalty here is neglible, because InitVLOG3__ is called
// once per site.
if (site_flag_value == level_default && !site_flag->base_name) {
site_flag->base_name = base;
site_flag->base_len = base_length;
site_flag->next = cached_site_list;
cached_site_list = site_flag;
}
}

// restore the errno in case something recoverable went wrong during
// the initialization of the VLOG mechanism (see above note "protect the..")
Expand Down

0 comments on commit 86fea1a

Please sign in to comment.